You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2015/11/05 16:42:04 UTC
[2/3] celix git commit: CELIX-273: Added dyn_message. To support
dynamicly allocation & serializing messages
CELIX-273: Added dyn_message. To support dynamicly allocation & serializing messages
Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/e1be5f1a
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/e1be5f1a
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/e1be5f1a
Branch: refs/heads/develop
Commit: e1be5f1aee386ece63e783a9a6d263a1a2b07678
Parents: b613302
Author: Pepijn Noltes <pe...@gmail.com>
Authored: Thu Nov 5 16:25:07 2015 +0100
Committer: Pepijn Noltes <pe...@gmail.com>
Committed: Thu Nov 5 16:25:07 2015 +0100
----------------------------------------------------------------------
.../remote_service_admin_dfi/CMakeLists.txt | 4 +-
.../dynamic_function_interface/CMakeLists.txt | 1 +
.../dynamic_function_interface/dyn_message.c | 322 +++++++++++++++++++
.../dynamic_function_interface/dyn_message.h | 38 +++
.../CMakeLists.txt | 1 +
.../descriptors/msg_example1.descriptor | 10 +
.../descriptors/msg_example2.descriptor | 12 +
.../descriptors/msg_example3.descriptor | 10 +
.../dyn_message_tests.cpp | 184 +++++++++++
9 files changed, 580 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/celix/blob/e1be5f1a/remote_services/remote_service_admin_dfi/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/CMakeLists.txt b/remote_services/remote_service_admin_dfi/CMakeLists.txt
index ba91105..275a991 100644
--- a/remote_services/remote_service_admin_dfi/CMakeLists.txt
+++ b/remote_services/remote_service_admin_dfi/CMakeLists.txt
@@ -16,7 +16,7 @@
# under the License.
-celix_subproject(RSA_REMOTE_SERVICE_ADMIN_DFI "Option to enable building the Remote Service Admin Service DFI" OFF)
+celix_subproject(RSA_REMOTE_SERVICE_ADMIN_DFI "Option to enable building the Remote Service Admin Service DFI" ON)
if (RSA_REMOTE_SERVICE_ADMIN_DFI)
@@ -44,4 +44,4 @@ if (RSA_REMOTE_SERVICE_ADMIN_DFI)
add_subdirectory(rsa_tst)
endif()
-endif()
\ No newline at end of file
+endif()
http://git-wip-us.apache.org/repos/asf/celix/blob/e1be5f1a/remote_services/remote_service_admin_dfi/dynamic_function_interface/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/CMakeLists.txt b/remote_services/remote_service_admin_dfi/dynamic_function_interface/CMakeLists.txt
index d7e1bf0..ea79768 100644
--- a/remote_services/remote_service_admin_dfi/dynamic_function_interface/CMakeLists.txt
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/CMakeLists.txt
@@ -29,6 +29,7 @@ add_library(dfi STATIC
dyn_type.c
dyn_function.c
dyn_interface.c
+ dyn_message.c
json_serializer.c
json_rpc.c
${MEMSTREAM_SOURCES}
http://git-wip-us.apache.org/repos/asf/celix/blob/e1be5f1a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_message.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_message.c b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_message.c
new file mode 100644
index 0000000..bfea35a
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_message.c
@@ -0,0 +1,322 @@
+/**
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#include "dyn_message.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "dyn_common.h"
+#include "dyn_type.h"
+
+DFI_SETUP_LOG(dynMessage);
+
+struct _dyn_message_type {
+ struct namvals_head header;
+ struct namvals_head annotations;
+ struct types_head types;
+ dyn_type *msgType;
+};
+
+static const int OK = 0;
+static const int ERROR = 1;
+
+static int dynMessage_parseSection(dyn_message_type *msg, FILE *stream);
+static int dynMessage_parseAnnotations(dyn_message_type *msg, FILE *stream);
+static int dynMessage_parseTypes(dyn_message_type *msg, FILE *stream);
+static int dynMessage_parseMessage(dyn_message_type *msg, FILE *stream);
+static int dynMessage_parseHeader(dyn_message_type *msg, FILE *stream);
+static int dynMessage_parseNameValueSection(dyn_message_type *msg, FILE *stream, struct namvals_head *head);
+static int dynMessage_checkMessage(dyn_message_type *msg);
+static int dynMessage_getEntryForHead(struct namvals_head *head, const char *name, char **value);
+
+int dynMessage_parse(FILE *descriptor, dyn_message_type **out) {
+ int status = OK;
+
+ dyn_message_type *msg = calloc(1, sizeof(*msg));
+ if (msg != NULL) {
+ TAILQ_INIT(&msg->header);
+ TAILQ_INIT(&msg->annotations);
+ TAILQ_INIT(&msg->types);
+
+ char peek = fgetc(descriptor);
+ while (peek == ':') {
+ ungetc(peek, descriptor);
+ status = dynMessage_parseSection(msg, descriptor);
+ if (status == OK) {
+ peek = fgetc(descriptor);
+ } else {
+ break;
+ }
+ }
+
+ if (status == OK) {
+ status = dynCommon_eatChar(descriptor, EOF);
+ }
+
+ if (status == OK) {
+ status = dynMessage_checkMessage(msg);
+ }
+ } else {
+ status = ERROR;
+ LOG_ERROR("Error allocating memory for dynamic message\n");
+ }
+
+ if (status == OK) {
+ *out = msg;
+ } else if (msg != NULL) {
+ dynMessage_destroy(msg);
+ }
+ return status;
+}
+
+static int dynMessage_checkMessage(dyn_message_type *msg) {
+ int status = OK;
+
+ //check header section
+ if (status == OK) {
+ bool foundType = false;
+ bool foundVersion = false;
+ bool foundName = false;
+ struct namval_entry *entry = NULL;
+ TAILQ_FOREACH(entry, &msg->header, entries) {
+ if (strcmp(entry->name, "type") == 0) {
+ foundType = true;
+ } else if (strcmp(entry->name, "version") == 0) {
+ foundVersion = true;
+ } else if (strcmp(entry->name, "name") == 0) {
+ foundName = true;
+ }
+ }
+
+ if (!foundType || !foundVersion || !foundName) {
+ status = ERROR;
+ LOG_ERROR("Parse Error. There must be a header section with a type, version and name entry");
+ }
+ }
+
+ return status;
+}
+
+static int dynMessage_parseSection(dyn_message_type *msg, FILE *stream) {
+ int status = OK;
+ char *sectionName = NULL;
+
+ status = dynCommon_eatChar(stream, ':');
+
+ if (status == OK) {
+ status = dynCommon_parseName(stream, §ionName);
+ }
+
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, '\n');
+ }
+
+ if (status == OK) {
+ if (strcmp("header", sectionName) == 0) {
+ status = dynMessage_parseHeader(msg, stream);
+ } else if (strcmp("annotations", sectionName) == 0) {
+ status = dynMessage_parseAnnotations(msg, stream);
+ } else if (strcmp("types", sectionName) == 0) {
+ status = dynMessage_parseTypes(msg, stream);
+ } else if (strcmp("message", sectionName) == 0) {
+ status = dynMessage_parseMessage(msg, stream);
+ } else {
+ status = ERROR;
+ LOG_ERROR("unsupported section '%s'", sectionName);
+ }
+ }
+
+ if (sectionName != NULL) {
+ free(sectionName);
+ }
+
+ return status;
+}
+
+static int dynMessage_parseHeader(dyn_message_type *msg, FILE *stream) {
+ return dynMessage_parseNameValueSection(msg, stream, &msg->header);
+}
+
+static int dynMessage_parseAnnotations(dyn_message_type *msg, FILE *stream) {
+ return dynMessage_parseNameValueSection(msg, stream, &msg->annotations);
+}
+
+static int dynMessage_parseNameValueSection(dyn_message_type *msg, FILE *stream, struct namvals_head *head) {
+ int status = OK;
+
+ int peek = fgetc(stream);
+ while (peek != ':' && peek != EOF) {
+ ungetc(peek, stream);
+
+ char *name;
+ char *value;
+ status = dynCommon_parseNameValue(stream, &name, &value);
+
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, '\n');
+ }
+
+ struct namval_entry *entry = NULL;
+ if (status == OK) {
+ entry = calloc(1, sizeof(*entry));
+ if (entry != NULL) {
+ entry->name = name;
+ entry->value = value;
+ TAILQ_INSERT_TAIL(head, entry, entries);
+ } else {
+ status = ERROR;
+ LOG_ERROR("Error allocating memory for namval entry");
+ }
+ }
+
+ if (status != OK) {
+ if (name != NULL) {
+ free(name);
+ }
+ if (value != NULL) {
+ free(value);
+ }
+ if (entry != NULL) {
+ free(entry);
+ }
+ break;
+ }
+ peek = fgetc(stream);
+ }
+ ungetc(peek, stream);
+
+ return status;
+}
+
+static int dynMessage_parseTypes(dyn_message_type *msg, FILE *stream) {
+ int status = OK;
+
+ //expected input (Name)=<Type>\n
+ int peek = fgetc(stream);
+ while (peek != ':' && peek != EOF) {
+ ungetc(peek, stream);
+
+ char *name;
+ status = dynCommon_parseName(stream, &name);
+
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, '=');
+ }
+
+ dyn_type *type = NULL;
+ if (status == OK) {
+ dynType_parse(stream, name, &msg->types, &type);
+ }
+ if (name != NULL) {
+ free(name);
+ }
+
+ if (status == OK) {
+ status = dynCommon_eatChar(stream, '\n');
+ }
+
+ struct type_entry *entry = NULL;
+ if (status == OK) {
+ entry = calloc(1, sizeof(*entry));
+ if (entry != NULL) {
+ entry->type = type;
+ TAILQ_INSERT_TAIL(&msg->types, entry, entries);
+ } else {
+ status = ERROR;
+ LOG_ERROR("Error allocating memory for type entry");
+ }
+ }
+
+ if (status != OK) {
+ if (type != NULL) {
+ dynType_destroy(type);
+ }
+ if (entry != NULL) {
+ free(entry);
+ }
+ break;
+ }
+ peek = fgetc(stream);
+ }
+ ungetc(peek, stream);
+
+ return status;
+}
+
+static int dynMessage_parseMessage(dyn_message_type *msg, FILE *stream) {
+ int status = OK;
+
+ //expected input <dynType>\n
+ char *name = NULL;
+ status = dynMessage_getName(msg, &name);
+
+ if (status == OK) {
+ status = dynType_parse(stream, name, &(msg->types), &(msg->msgType));
+ }
+
+ return status;
+}
+
+void dynMessage_destroy(dyn_message_type *msg) {
+ if (msg != NULL) {
+ dynCommon_clearNamValHead(&msg->header);
+ dynCommon_clearNamValHead(&msg->annotations);
+
+ struct type_entry *tmp = NULL;
+ struct type_entry *tInfo = TAILQ_FIRST(&msg->types);
+ while (tInfo != NULL) {
+ tmp = tInfo;
+ tInfo = TAILQ_NEXT(tInfo, entries);
+ dynType_destroy(tmp->type);
+ free(tmp);
+ }
+
+ if (msg->msgType != NULL) {
+ dynType_destroy(msg->msgType);
+ }
+
+ free(msg);
+ }
+}
+
+int dynMessage_getName(dyn_message_type *msg, char **out) {
+ return dynMessage_getEntryForHead(&msg->header, "name", out);
+}
+
+int dynMessage_getVersion(dyn_message_type *msg, char **version) {
+ return dynMessage_getEntryForHead(&msg->header, "version", version);
+}
+
+int dynMessage_getHeaderEntry(dyn_message_type *msg, const char *name, char **value) {
+ return dynMessage_getEntryForHead(&msg->header, name, value);
+}
+
+int dynMessage_getAnnotationEntry(dyn_message_type *msg, const char *name, char **value) {
+ return dynMessage_getEntryForHead(&msg->annotations, name, value);
+}
+
+static int dynMessage_getEntryForHead(struct namvals_head *head, const char *name, char **out) {
+ int status = OK;
+ char *value = NULL;
+ struct namval_entry *entry = NULL;
+ TAILQ_FOREACH(entry, head, entries) {
+ if (strcmp(name, entry->name) == 0) {
+ value = entry->value;
+ break;
+ }
+ }
+ if (value != NULL) {
+ *out = value;
+ } else {
+ status = ERROR;
+ LOG_WARNING("Cannot find '%s' in list", name);
+ }
+ return status;
+}
+
+int dynMessage_getMessageType(dyn_message_type *msg, dyn_type **type) {
+ int status = OK;
+ *type = msg->msgType;
+ return status;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/e1be5f1a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_message.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_message.h b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_message.h
new file mode 100644
index 0000000..1116ab3
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_message.h
@@ -0,0 +1,38 @@
+/*
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#ifndef __DYN_MESSAGE_H_
+#define __DYN_MESSAGE_H_
+
+#include "dyn_common.h"
+#include "dyn_type.h"
+#include "dfi_log_util.h"
+
+DFI_SETUP_LOG_HEADER(dynMessage);
+
+/* Description string
+ *
+ * Descriptor (message) = HeaderSection AnnotationSection TypesSection MessageSection
+ *
+ * HeaderSection=
+ * ':header\n' [NameValue]*
+ * ':annotations\n' [NameValue]*
+ * ':types\n' [TypeIdValue]*
+ * ':message\n' [MessageIdValue]
+ *
+ */
+typedef struct _dyn_message_type dyn_message_type;
+
+
+int dynMessage_parse(FILE *descriptor, dyn_message_type **out);
+void dynMessage_destroy(dyn_message_type *msg);
+
+int dynMessage_getName(dyn_message_type *msg, char **name);
+int dynMessage_getVersion(dyn_message_type *msg, char **version);
+int dynMessage_getHeaderEntry(dyn_message_type *msg, const char *name, char **value);
+int dynMessage_getAnnotationEntry(dyn_message_type *msg, const char *name, char **value);
+int dynMessage_getMessageType(dyn_message_type *msg, dyn_type **type);
+
+
+
+#endif
http://git-wip-us.apache.org/repos/asf/celix/blob/e1be5f1a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/CMakeLists.txt b/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/CMakeLists.txt
index bfb0f58..3c8a800 100644
--- a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/CMakeLists.txt
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/CMakeLists.txt
@@ -24,6 +24,7 @@ add_executable(test_dfi
dyn_function_tests.cpp
dyn_closure_tests.cpp
dyn_interface_tests.cpp
+ dyn_message_tests.cpp
json_serializer_tests.cpp
json_rpc_tests.cpp
run_tests.cpp
http://git-wip-us.apache.org/repos/asf/celix/blob/e1be5f1a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/descriptors/msg_example1.descriptor
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/descriptors/msg_example1.descriptor b/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/descriptors/msg_example1.descriptor
new file mode 100644
index 0000000..576523a
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/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/e1be5f1a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/descriptors/msg_example2.descriptor
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/descriptors/msg_example2.descriptor b/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/descriptors/msg_example2.descriptor
new file mode 100644
index 0000000..128049d
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/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/e1be5f1a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/descriptors/msg_example3.descriptor
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/descriptors/msg_example3.descriptor b/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/descriptors/msg_example3.descriptor
new file mode 100644
index 0000000..7b69380
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/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/e1be5f1a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/dyn_message_tests.cpp
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/dyn_message_tests.cpp b/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/dyn_message_tests.cpp
new file mode 100644
index 0000000..e30d16e
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface_tst/dyn_message_tests.cpp
@@ -0,0 +1,184 @@
+/**
+ *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 *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 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);
+
+ char *version = NULL;
+ status = dynMessage_getVersion(dynMsg, &version);
+ CHECK_EQUAL(0, status);
+ STRCMP_EQUAL("1.0.0", version);
+
+ 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);
+
+ char *version = NULL;
+ status = dynMessage_getVersion(dynMsg, &version);
+ CHECK_EQUAL(0, status);
+ STRCMP_EQUAL("0.0.1", version);
+
+ 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);
+
+ char *version = NULL;
+ status = dynMessage_getVersion(dynMsg, &version);
+ CHECK_EQUAL(0, status);
+ STRCMP_EQUAL("1.0.0", version);
+
+ 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);
+}
+
+}
+
+
+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();
+}