http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/open_memstream.h ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/open_memstream.h b/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/open_memstream.h new file mode 100644 index 0000000..e87bb0a --- /dev/null +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/memstream/open_memstream.h @@ -0,0 +1,15 @@ +#ifndef OPEN_MEMSTREAM_H_ +#define OPEN_MEMSTREAM_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +FILE *open_memstream(char **cp, size_t *lenp); + +#ifdef __cplusplus +} +#endif + +#endif // #ifndef FMEMOPEN_H_
http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/complex.avdl ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/complex.avdl b/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/complex.avdl new file mode 100644 index 0000000..0490dcd --- /dev/null +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/complex.avdl @@ -0,0 +1,11 @@ +protocol Complex { + + record StatResult { + double sum; + double min; + double max; + array<double> input; + } + + StatResult stats(array<double> input); +} http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/complex.avpr ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/complex.avpr b/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/complex.avpr new file mode 100644 index 0000000..0577397 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/complex.avpr @@ -0,0 +1,36 @@ +{ + "protocol" : "Complex", + "namespace" : null, + "types" : [ { + "type" : "record", + "name" : "StatResult", + "fields" : [ { + "name" : "sum", + "type" : "double" + }, { + "name" : "min", + "type" : "double" + }, { + "name" : "max", + "type" : "double" + }, { + "name" : "input", + "type" : { + "type" : "array", + "items" : "double" + } + } ] + } ], + "messages" : { + "stats" : { + "request" : [ { + "name" : "input", + "type" : { + "type" : "array", + "items" : "double" + } + } ], + "response" : "StatResult" + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/invalid1.avpr ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/invalid1.avpr b/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/invalid1.avpr new file mode 100644 index 0000000..c968c61 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/invalid1.avpr @@ -0,0 +1,29 @@ +{ + "protocol" : "Complex", + "namespace" : null, + "types" : [ { + "type" : "record", + "name" : "StatResult", + "fields" : [ { + "name" : "sum", + "type" : "double" + }, { + "name" : "min", + "type" : "double" + }, { + "name" : "max", + "type" : "double" + }, { + "name" : "input", + "type" : { + "type" : "array", + "items" : "double" + } + } ] + } ], + "messages" : { + "stats" : { + "response" : "StatResult" + } + } +} http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/invalid2.avpr ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/invalid2.avpr b/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/invalid2.avpr new file mode 100644 index 0000000..fc48ca9 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/invalid2.avpr @@ -0,0 +1,31 @@ +{ + "protocol" : "Simple", + "types" : [ ], + "messages" : { + "sum" : { + "request" : [ { + "name" : "a" + }, { + "name" : "b", + "type" : "double" + } ], + "response" : "double" + }, + "sub" : { + "request" : [ { + "name" : "a", + "type" : "double" + }, { + "name" : "b", + "type" : "double" + } ], + "response" : "double" + }, + "sqrt" : { + "request" : [ { + "name" : "a" + } ], + "response" : "double" + } + } +} http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/simple.avdl ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/simple.avdl b/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/simple.avdl new file mode 100644 index 0000000..cd5cafe --- /dev/null +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/simple.avdl @@ -0,0 +1,6 @@ +@namespace("org.apache.avro.test") +protocol Simple { + double sum(double a, double b); + double sub(double a, double b); + double sqrt(double a); +} http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/simple.avpr ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/simple.avpr b/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/simple.avpr new file mode 100644 index 0000000..8a90bb2 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/simple.avpr @@ -0,0 +1,33 @@ +{ + "protocol" : "Simple", + "types" : [ ], + "messages" : { + "sum" : { + "request" : [ { + "name" : "a", + "type" : "double" + }, { + "name" : "b", + "type" : "double" + } ], + "response" : "double" + }, + "sub" : { + "request" : [ { + "name" : "a", + "type" : "double" + }, { + "name" : "b", + "type" : "double" + } ], + "response" : "double" + }, + "sqrt" : { + "request" : [ { + "name" : "a", + "type" : "double" + } ], + "response" : "double" + } + } +} http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/simple_min.avpr ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/simple_min.avpr b/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/simple_min.avpr new file mode 100644 index 0000000..c2bce19 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/schemas/simple_min.avpr @@ -0,0 +1 @@ +{"protocol":"Simple","types":[],"messages":{"sum":{"request":[{"name":"a","type":"double"},{"name":"b","type":"double"}],"response":"double"},"sub":{"request":[{"name":"a","type":"double"},{"name":"b","type":"double"}],"response":"double"},"sqrt":{"request":[{"name":"a","type":"double"}],"response":"double"}}} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/avro_descriptor_translator_tests.cpp ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/avro_descriptor_translator_tests.cpp b/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/avro_descriptor_translator_tests.cpp new file mode 100644 index 0000000..63401e5 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/avro_descriptor_translator_tests.cpp @@ -0,0 +1,164 @@ +/** + * Licensed under Apache License v2. See LICENSE for more information. + */ +#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"); + } + + + 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/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_closure_tests.cpp ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_closure_tests.cpp b/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_closure_tests.cpp new file mode 100644 index 0000000..b2b11d7 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_closure_tests.cpp @@ -0,0 +1,146 @@ +/* + * Licensed under Apache License v2. See LICENSE for more information. + */ +#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 *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"); +} + +#define EXAMPLE1_DESCRIPTOR "example(III)I" +static void example1_binding(void *userData, 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 *userData, 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 *userData, 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() { + dynFunction_logSetup(stdLog, NULL, 3); + dynType_logSetup(stdLog, NULL, 3); + //TODO dynType_logSetup(stdLog, NULL, 4); + dynCommon_logSetup(stdLog, NULL, 3); + g_count = 0; + } +}; + +TEST(DynClosureTests, DynCLosureTest1) { + //TODO split up + tests(); +} http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_function_tests.cpp ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_function_tests.cpp b/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_function_tests.cpp new file mode 100644 index 0000000..410b3ec --- /dev/null +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_function_tests.cpp @@ -0,0 +1,115 @@ +/* + * Licensed under Apache License v2. See LICENSE for more information. + */ +#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 *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"); + } + + #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); + } +} + +TEST_GROUP(DynFunctionTests) { + void setup() { + dynFunction_logSetup(stdLog, NULL, 3); + dynType_logSetup(stdLog, NULL, 3); + dynCommon_logSetup(stdLog, NULL, 3); + } +}; + +TEST(DynFunctionTests, DynFuncTest1) { + test_example1(); +} + +TEST(DynFunctionTests, DynFuncTest2) { + test_example2(); +} http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_interface_tests.cpp ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_interface_tests.cpp b/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_interface_tests.cpp new file mode 100644 index 0000000..6453afd --- /dev/null +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_interface_tests.cpp @@ -0,0 +1,79 @@ +/* + * Licensed under Apache License v2. See LICENSE for more information. + */ +#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 *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"); + } + + 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); + + char *version = NULL; + status = dynInterface_getVersion(dynIntf, &version); + CHECK_EQUAL(0, status); + STRCMP_EQUAL("1.0.0", version); + + 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); + + dynInterface_destroy(dynIntf); + } + +} + + +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(); +} http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_type_tests.cpp ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_type_tests.cpp b/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_type_tests.cpp new file mode 100644 index 0000000..96f64fa --- /dev/null +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_type_tests.cpp @@ -0,0 +1,190 @@ +/* + * Licensed under Apache License v2. See LICENSE for more information. + */ +#include <CppUTest/TestHarness.h> +#include "CppUTest/CommandLineTestRunner.h" + +extern "C" { + #include <string.h> + #include <stdarg.h> + + #include "dyn_common.h" + #include "dyn_type.h" + + 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"); + } + + static void runTest(const char *descriptorStr, const char *exName) { + dyn_type *type; + int i; + 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); + + 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, 0); + } +}; + +#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 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) + +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); +} + http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/json_serializer_tests.cpp ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/json_serializer_tests.cpp b/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/json_serializer_tests.cpp new file mode 100644 index 0000000..c21d594 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/json_serializer_tests.cpp @@ -0,0 +1,398 @@ +/** + * Licensed under Apache License v2. See LICENSE for more information. + */ +#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 <ffi.h> + +#include "dyn_common.h" +#include "dyn_type.h" +#include "json_serializer.h" + +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"); +} + +/*********** example 1 ************************/ +/** struct type ******************************/ +const char *example1_descriptor = "{DJISF a b c d e}"; + +const char *example1_input = "{ \ + \"a\" : 1.0, \ + \"b\" : 22, \ + \"c\" : 32, \ + \"d\" : 42, \ + \"e\" : 4.4 \ +}"; + +struct example1 { + double a; //0 + int64_t b; //1 + int32_t c; //2 + int16_t d; //3 + float e; //4 +}; + +static void check_example1(void *data) { + struct example1 *ex = (struct example1 *)data; + CHECK_EQUAL(1.0, ex->a); + CHECK_EQUAL(22, ex->b); + CHECK_EQUAL(32, ex->c); + CHECK_EQUAL(42, ex->d); + CHECK_EQUAL(4.4f, ex->e); +} + +/*********** example 2 ************************/ +const char *example2_descriptor = "{BJJDFD byte long1 long2 double1 float1 double2}"; + +const char *example2_input = "{ \ + \"byte\" : 42, \ + \"long1\" : 232, \ + \"long2\" : 242, \ + \"double1\" : 4.2, \ + \"float1\" : 3.2, \ + \"double2\" : 4.4 \ +}"; + +struct example2 { + char byte; //0 + int64_t long1; //1 + int64_t long2; //2 + double double1; //3 + float float1; //4 + double double2; //5 +}; + +static void check_example2(void *data) { + struct example2 *ex = (struct example2 *)data; + CHECK_EQUAL(42, ex->byte); + CHECK_EQUAL(232, ex->long1); + CHECK_EQUAL(242, ex->long2); + CHECK_EQUAL(4.2, ex->double1); + CHECK_EQUAL(3.2f, ex->float1); + CHECK_EQUAL(4.4, ex->double2); +} + + +/*********** example 3 ************************/ +/** sequence with a simple type **************/ +const char *example3_descriptor = "{[I numbers}"; + +const char *example3_input = "{ \ + \"numbers\" : [22,32,42] \ +}"; + +struct example3 { + struct { + uint32_t cap; + uint32_t len; + int32_t *buf; + } numbers; +}; + +static void check_example3(void *data) { + struct example3 *ex = (struct example3 *)data; + CHECK_EQUAL(3, ex->numbers.len); + CHECK_EQUAL(22, ex->numbers.buf[0]); + CHECK_EQUAL(32, ex->numbers.buf[1]); + CHECK_EQUAL(42, ex->numbers.buf[2]); +} + +/*********** example 4 ************************/ +/** structs within a struct (by reference)*******/ +const char *example4_descriptor = "{{IDD index val1 val2}{IDD index val1 val2} left right}"; + +static const char *example4_input = "{ \ + \"left\" : {\"index\":1, \"val1\":1.0, \"val2\":2.0 }, \ + \"right\" : {\"index\":2, \"val1\":5.0, \"val2\":4.0 } \ +}"; + +struct ex4_leaf { + int32_t index; + double val1; + double val2; +}; + +struct example4 { + struct ex4_leaf left; + struct ex4_leaf right; +}; + +static void check_example4(void *data) { + struct example4 *ex = (struct example4 *)data; + CHECK_EQUAL(1, ex->left.index); + CHECK_EQUAL(1.0, ex->left.val1); + CHECK_EQUAL(2.0, ex->left.val2); + CHECK_EQUAL(2, ex->right.index); + CHECK_EQUAL(5.0, ex->right.val1); + CHECK_EQUAL(4.0, ex->right.val2); +} + + +/*********** example 4 ************************/ +/** structs within a struct (by reference)*******/ +const char *example5_descriptor = "Tleaf={ts name age};Tnode={Lnode;Lnode;Lleaf; left right value};{Lnode; head}"; + +static const char *example5_input = "{ \ + \"head\" : {\ + \"left\" : {\ + \"value\" : {\ + \"name\" : \"John\",\ + \"age\" : 44 \ + }\ + },\ + \"right\" : {\ + \"value\" : {\ + \"name\" : \"Peter\", \ + \"age\" : 55 \ + }\ + }\ + }\ +}"; + +struct leaf { + const char *name; + uint16_t age; +}; + +struct node { + struct node *left; + struct node *right; + struct leaf *value; +}; + +struct example5 { + struct node *head; +}; + +static void check_example5(void *data) { + struct example5 *ex = (struct example5 *)data; + CHECK_TRUE(ex->head != NULL); + + CHECK(ex->head->left != NULL); + CHECK(ex->head->left->value != NULL); + STRCMP_EQUAL("John", ex->head->left->value->name); + CHECK_EQUAL(44, ex->head->left->value->age); + CHECK(ex->head->left->left == NULL); + CHECK(ex->head->left->right == NULL); + + CHECK(ex->head->right != NULL); + CHECK(ex->head->right->value != NULL); + STRCMP_EQUAL("Peter", ex->head->right->value->name); + CHECK_EQUAL(55, ex->head->right->value->age); + CHECK(ex->head->right->left == NULL); + CHECK(ex->head->right->right == NULL); +} + +static void parseTests(void) { + dyn_type *type; + void *inst; + int rc; + + type = NULL; + inst = NULL; + rc = dynType_parseWithStr(example1_descriptor, NULL, NULL, &type); + CHECK_EQUAL(0, rc); + rc = jsonSerializer_deserialize(type, example1_input, &inst); + CHECK_EQUAL(0, rc); + check_example1(inst); + dynType_free(type, inst); + dynType_destroy(type); + + type = NULL; + inst = NULL; + rc = dynType_parseWithStr(example2_descriptor, NULL, NULL, &type); + CHECK_EQUAL(0, rc); + rc = jsonSerializer_deserialize(type, example2_input, &inst); + CHECK_EQUAL(0, rc); + check_example2(inst); + dynType_free(type, inst); + dynType_destroy(type); + + type = NULL; + inst = NULL; + rc = dynType_parseWithStr(example3_descriptor, NULL, NULL, &type); + CHECK_EQUAL(0, rc); + rc = jsonSerializer_deserialize(type, example3_input, &inst); + CHECK_EQUAL(0, rc); + check_example3(inst); + dynType_free(type, inst); + dynType_destroy(type); + + type = NULL; + inst = NULL; + rc = dynType_parseWithStr(example4_descriptor, NULL, NULL, &type); + CHECK_EQUAL(0, rc); + rc = jsonSerializer_deserialize(type, example4_input, &inst); + CHECK_EQUAL(0, rc); + check_example4(inst); + dynType_free(type, inst); + dynType_destroy(type); + + type = NULL; + inst = NULL; + rc = dynType_parseWithStr(example5_descriptor, NULL, NULL, &type); + CHECK_EQUAL(0, rc); + rc = jsonSerializer_deserialize(type, example5_input, &inst); + CHECK_EQUAL(0, rc); + check_example5(inst); + dynType_free(type, inst); + dynType_destroy(type); +} + +const char *write_example1_descriptor = "{BSIJsijFDN a b c d e f g h i j}"; + +struct write_example1 { + char a; + int16_t b; + int32_t c; + int64_t d; + uint16_t e; + uint32_t f; + uint64_t g; + float h; + double i; + int j; +}; + +void writeTest1(void) { + struct write_example1 ex1 = {.a=1, .b=2, .c=3, .d=4, .e=5, .f=6, .g=7, .h=8.8f, .i=9.9, .j=10}; + dyn_type *type = NULL; + char *result = NULL; + int rc = dynType_parseWithStr(write_example1_descriptor, "ex1", NULL, &type); + CHECK_EQUAL(0, rc); + rc = jsonSerializer_serialize(type, &ex1, &result); + CHECK_EQUAL(0, rc); + STRCMP_CONTAINS("\"a\":1", result); + STRCMP_CONTAINS("\"b\":2", result); + STRCMP_CONTAINS("\"c\":3", result); + STRCMP_CONTAINS("\"d\":4", result); + STRCMP_CONTAINS("\"e\":5", result); + STRCMP_CONTAINS("\"f\":6", result); + STRCMP_CONTAINS("\"g\":7", result); + STRCMP_CONTAINS("\"h\":8.8", result); + STRCMP_CONTAINS("\"i\":9.9", result); + STRCMP_CONTAINS("\"j\":10", result); + //printf("example 1 result: '%s'\n", result); + dynType_destroy(type); + free(result); +} + +const char *write_example2_descriptor = "{*{JJ a b}{SS c d} sub1 sub2}"; + +struct write_example2_sub { + int64_t a; + int64_t b; +}; + +struct write_example2 { + struct write_example2_sub *sub1; + struct { + int16_t c; + int16_t d; + } sub2; +}; + +void writeTest2(void) { + struct write_example2_sub sub1 = { .a = 1, .b = 2 }; + struct write_example2 ex = { .sub1 = &sub1 }; + ex.sub2.c = 3; + ex.sub2.d = 4; + + dyn_type *type = NULL; + char *result = NULL; + int rc = dynType_parseWithStr(write_example2_descriptor, "ex2", NULL, &type); + CHECK_EQUAL(0, rc); + rc = jsonSerializer_serialize(type, &ex, &result); + CHECK_EQUAL(0, rc); + STRCMP_CONTAINS("\"a\":1", result); + STRCMP_CONTAINS("\"b\":2", result); + STRCMP_CONTAINS("\"c\":3", result); + STRCMP_CONTAINS("\"d\":4", result); + //printf("example 2 result: '%s'\n", result); + dynType_destroy(type); + free(result); +} + +const char *write_example3_descriptor = "Tperson={ti name age};[Lperson;"; + +struct write_example3_person { + const char *name; + uint32_t age; +}; + +struct write_example3 { + uint32_t cap; + uint32_t len; + struct write_example3_person **buf; +}; + +void writeTest3(void) { + struct write_example3_person p1 = {.name = "John", .age = 33}; + struct write_example3_person p2 = {.name = "Peter", .age = 44}; + struct write_example3_person p3 = {.name = "Carol", .age = 55}; + struct write_example3_person p4 = {.name = "Elton", .age = 66}; + struct write_example3 seq; + seq.buf = (struct write_example3_person **) calloc(4, sizeof(void *)); + seq.len = seq.cap = 4; + seq.buf[0] = &p1; + seq.buf[1] = &p2; + seq.buf[2] = &p3; + seq.buf[3] = &p4; + + dyn_type *type = NULL; + char *result = NULL; + int rc = dynType_parseWithStr(write_example3_descriptor, "ex3", NULL, &type); + CHECK_EQUAL(0, rc); + rc = jsonSerializer_serialize(type, &seq, &result); + CHECK_EQUAL(0, rc); + STRCMP_CONTAINS("\"age\":33", result); + STRCMP_CONTAINS("\"age\":44", result); + STRCMP_CONTAINS("\"age\":55", result); + STRCMP_CONTAINS("\"age\":66", result); + //printf("example 3 result: '%s'\n", result); + free(seq.buf); + dynType_destroy(type); + free(result); +} + +} + +TEST_GROUP(JsonSerializerTests) { + void setup() { + int lvl = 1; + dynCommon_logSetup(stdLog, NULL, lvl); + dynType_logSetup(stdLog, NULL,lvl); + jsonSerializer_logSetup(stdLog, NULL, lvl); + } +}; + +TEST(JsonSerializerTests, ParseTests) { + //TODO split up + parseTests(); +} + +TEST(JsonSerializerTests, WriteTest1) { + writeTest1(); +} + +TEST(JsonSerializerTests, WriteTest2) { + writeTest2(); +} + +TEST(JsonSerializerTests, WriteTest3) { + writeTest3(); +} http://git-wip-us.apache.org/repos/asf/celix/blob/bf76d213/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/run_tests.cpp ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/run_tests.cpp b/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/run_tests.cpp new file mode 100644 index 0000000..f405c9f --- /dev/null +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/run_tests.cpp @@ -0,0 +1,9 @@ +/* + * Licensed under Apache License v2. See LICENSE for more information. + */ +#include <CppUTest/TestHarness.h> +#include "CppUTest/CommandLineTestRunner.h" + +int main(int argc, char** argv) { + return RUN_ALL_TESTS(argc, argv); +}