Bläddra i källkod

Add missing statuscodes from StatusCode.csv

Add conversion from UA_StatusCode to human-readable string message. Fix #847

Add unit test for UA_StatusCode_msg and add to example

Add Opc.Ua.StatusCodes.csv for UA_StatusCode_msg
Stefan Profanter 7 år sedan
förälder
incheckning
4c9857e122

+ 15 - 0
CMakeLists.txt

@@ -48,6 +48,7 @@ option(UA_ENABLE_MULTITHREADING "Enable multithreading" OFF)
 option(UA_ENABLE_AMALGAMATION "Concatenate the library to a single file open62541.h/.c" OFF)
 option(UA_ENABLE_COVERAGE "Enable gcov coverage" OFF)
 option(BUILD_SHARED_LIBS "Enable building of shared libraries (dll/so)" OFF)
+option(UA_ENABLE_STATUSCODE_MSG "Enable conversion of StatusCode to human-readable error message" OFF)
 
 if(UA_ENABLE_COVERAGE)
   set(CMAKE_BUILD_TYPE DEBUG)
@@ -294,6 +295,20 @@ add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_nodeids.h
                    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_nodeids.py
                            ${CMAKE_CURRENT_SOURCE_DIR}/tools/schema/NodeIds.csv)
 
+if(UA_ENABLE_STATUSCODE_MSG)
+    # StatusCode to String
+    add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_statuscode_msg_table.c
+            PRE_BUILD
+            COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_statuscode_msg.py
+            ${PROJECT_SOURCE_DIR}/tools/schema/Opc.Ua.StatusCodes.csv ${PROJECT_BINARY_DIR}/src_generated/ua_statuscode_msg_table
+            DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_statuscode_msg.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/tools/schema/Opc.Ua.StatusCodes.csv)
+
+    list(APPEND exported_headers ${PROJECT_SOURCE_DIR}/include/ua_statuscode_msg.h)
+    list(APPEND lib_sources ${PROJECT_BINARY_DIR}/src_generated/ua_statuscode_msg_table.c)
+    list(APPEND lib_sources ${PROJECT_SOURCE_DIR}/src/ua_statuscode_msg.c)
+endif()
+
 # generated namespace 0
 add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_namespaceinit_generated.c
                           ${PROJECT_BINARY_DIR}/src_generated/ua_namespaceinit_generated.h

+ 1 - 1
doc/tutorial_client_firstSteps.rst

@@ -8,7 +8,7 @@ creating a server. Copy the following into a file `myClient.c`:
 .. literalinclude:: client_firstSteps.c
    :language: c
    :linenos:
-   :lines: 4,5,12,14-
+   :lines: 4,5,14,17-
 
 Compilation is similar to the server example.
 

+ 6 - 1
examples/client_firstSteps.c

@@ -7,7 +7,9 @@
 #ifdef UA_NO_AMALGAMATION
 #include "ua_client.h"
 #include "ua_config_standard.h"
-#include "ua_network_tcp.h"
+#ifdef UA_ENABLE_STATUSCODE_MSG
+#include "ua_statuscode_msg.h"
+#endif
 #else
 #include "open62541.h"
 #endif
@@ -16,6 +18,9 @@ int main(void) {
     UA_Client *client = UA_Client_new(UA_ClientConfig_standard);
     UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:16664");
     if(retval != UA_STATUSCODE_GOOD) {
+#ifdef UA_ENABLE_STATUSCODE_MSG
+	    printf("Client connect failed: %s - %s", UA_StatusCode_name(retval), UA_StatusCode_msg(retval));
+#endif
         UA_Client_delete(client);
         return (int)retval;
     }

+ 1 - 0
include/ua_config.h.in

@@ -29,6 +29,7 @@ extern "C" {
 #cmakedefine UA_ENABLE_GENERATE_NAMESPACE0
 #cmakedefine UA_ENABLE_EXTERNAL_NAMESPACES
 #cmakedefine UA_ENABLE_NODEMANAGEMENT
+#cmakedefine UA_ENABLE_STATUSCODE_MSG
 
 #cmakedefine UA_ENABLE_EMBEDDED_LIBC
 

+ 24 - 13
include/ua_constants.h

@@ -137,8 +137,9 @@ typedef enum {
 #define UA_STATUSCODE_BADCERTIFICATEUNTRUSTED 0x801a0000 // The Certificate is not trusted.
 #define UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN 0x801b0000 // It was not possible to determine if the Certificate has been revoked.
 #define UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN 0x801c0000 // It was not possible to determine if the Issuer Certificate has been revoked.
-#define UA_STATUSCODE_BADCERTIFICATEREVOKED 0x801d0000 // The Certificate has been revoked.
-#define UA_STATUSCODE_BADCERTIFICATEISSUERREVOKED 0x801e0000 // The Issuer Certificate has been revoked.
+#define UA_STATUSCODE_BADCERTIFICATEREVOKED 0x801d0000 // The certificate has been revoked.
+#define UA_STATUSCODE_BADCERTIFICATEISSUERREVOKED 0x801e0000 // The issuer certificate has been revoked.
+#define UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE 0x810d0000 // The certificate chain is incomplete.
 #define UA_STATUSCODE_BADUSERACCESSDENIED 0x801f0000 // User does not have permission to perform the requested operation.
 #define UA_STATUSCODE_BADIDENTITYTOKENINVALID 0x80200000 // The user identity token is not valid.
 #define UA_STATUSCODE_BADIDENTITYTOKENREJECTED 0x80210000 // The user identity token is valid but the server has rejected it.
@@ -152,11 +153,12 @@ typedef enum {
 #define UA_STATUSCODE_BADREQUESTHEADERINVALID 0x802a0000 // The header for the request is missing or invalid.
 #define UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID 0x802b0000 // The timestamps to return parameter is invalid.
 #define UA_STATUSCODE_BADREQUESTCANCELLEDBYCLIENT 0x802c0000 // The request was cancelled by the client.
+#define UA_STATUSCODE_BADTOOMANYARGUMENTS 0x80e50000 // Too many arguments were provided.
 #define UA_STATUSCODE_GOODSUBSCRIPTIONTRANSFERRED 0x002d0000 // The subscription was transferred to another session.
 #define UA_STATUSCODE_GOODCOMPLETESASYNCHRONOUSLY 0x002e0000 // The processing will complete asynchronously.
 #define UA_STATUSCODE_GOODOVERLOAD 0x002f0000 // Sampling has slowed down due to resource limitations.
 #define UA_STATUSCODE_GOODCLAMPED 0x00300000 // The value written was accepted but was clamped.
-#define UA_STATUSCODE_BADNOCOMMUNICATION 0x80310000 // Communication with the data source is defined, but not established and there is no last known value available.
+#define UA_STATUSCODE_BADNOCOMMUNICATION 0x80310000 // Communication with the data source is defined
 #define UA_STATUSCODE_BADWAITINGFORINITIALDATA 0x80320000 // Waiting for the server to obtain values from the underlying data source.
 #define UA_STATUSCODE_BADNODEIDINVALID 0x80330000 // The syntax of the node id is not valid.
 #define UA_STATUSCODE_BADNODEIDUNKNOWN 0x80340000 // The node id refers to a node that does not exist in the server address space.
@@ -180,8 +182,8 @@ typedef enum {
 #define UA_STATUSCODE_BADSTRUCTUREMISSING 0x80460000 // A mandatory structured parameter was missing or null.
 #define UA_STATUSCODE_BADEVENTFILTERINVALID 0x80470000 // The event filter is not valid.
 #define UA_STATUSCODE_BADCONTENTFILTERINVALID 0x80480000 // The content filter is not valid.
-#define UA_STATUSCODE_BADFILTEROPERATORINVALID 0x80c10000 // An unrecognized operator was provided in a filter.
-#define UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED 0x80c20000 // A valid operator was provided but the server does not provide support for this filter operator.
+#define UA_STATUSCODE_BADFILTEROPERATORINVALID 0x80c10000 // An unregognized operator was provided in a filter.
+#define UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED 0x80c20000 // A valid operator was provided
 #define UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH 0x80c30000 // The number of operands provided for the filter operator was less then expected for the operand provided.
 #define UA_STATUSCODE_BADFILTEROPERANDINVALID 0x80490000 // The operand used in a content filter is not valid.
 #define UA_STATUSCODE_BADFILTERELEMENTINVALID 0x80c40000 // The referenced element is not a valid element in the content filter.
@@ -203,7 +205,7 @@ typedef enum {
 #define UA_STATUSCODE_BADAPPLICATIONSIGNATUREINVALID 0x80580000 // The signature generated with the client certificate is missing or invalid.
 #define UA_STATUSCODE_BADNOVALIDCERTIFICATES 0x80590000 // The client did not provide at least one software certificate that is valid and meets the profile requirements for the server.
 #define UA_STATUSCODE_BADIDENTITYCHANGENOTSUPPORTED 0x80c60000 // The Server does not support changing the user identity assigned to the session.
-#define UA_STATUSCODE_BADREQUESTCANCELLEDBYREQUEST 0x805a0000 // The request was canceled by the client with the Cancel service.
+#define UA_STATUSCODE_BADREQUESTCANCELLEDBYREQUEST 0x805a0000 // The request was cancelled by the client with the Cancel service.
 #define UA_STATUSCODE_BADPARENTNODEIDINVALID 0x805b0000 // The parent node id does not to refer to a valid node.
 #define UA_STATUSCODE_BADREFERENCENOTALLOWED 0x805c0000 // The reference could not be created because it violates constraints imposed by the data model.
 #define UA_STATUSCODE_BADNODEIDREJECTED 0x805d0000 // The requested node id was reject because it was either invalid or server does not allow node ids to be specified by the client.
@@ -233,10 +235,11 @@ typedef enum {
 #define UA_STATUSCODE_BADQUERYTOOCOMPLEX 0x806e0000 // The requested operation requires too many resources in the server.
 #define UA_STATUSCODE_BADNOMATCH 0x806f0000 // The requested operation has no match to return.
 #define UA_STATUSCODE_BADMAXAGEINVALID 0x80700000 // The max age parameter is invalid.
+#define UA_STATUSCODE_BADSECURITYMODEINSUFFICIENT 0x80e60000 // The operation is not permitted over the current secure channel.
 #define UA_STATUSCODE_BADHISTORYOPERATIONINVALID 0x80710000 // The history details parameter is not valid.
 #define UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED 0x80720000 // The server does not support the requested operation.
 #define UA_STATUSCODE_BADINVALIDTIMESTAMPARGUMENT 0x80bd0000 // The defined timestamp to return was invalid.
-#define UA_STATUSCODE_BADWRITENOTSUPPORTED 0x80730000 // The server not does support writing the combination of value status and timestamps provided.
+#define UA_STATUSCODE_BADWRITENOTSUPPORTED 0x80730000 // The server not does support writing the combination of value
 #define UA_STATUSCODE_BADTYPEMISMATCH 0x80740000 // The value supplied for the attribute is not of the same type as the attribute's value.
 #define UA_STATUSCODE_BADMETHODINVALID 0x80750000 // The method id does not refer to a method for the specified object.
 #define UA_STATUSCODE_BADARGUMENTSMISSING 0x80760000 // The client did not specify all of the input arguments for the method.
@@ -261,7 +264,7 @@ typedef enum {
 #define UA_STATUSCODE_BADSEQUENCENUMBERINVALID 0x80880000 // The sequence number is not valid.
 #define UA_STATUSCODE_BADPROTOCOLVERSIONUNSUPPORTED 0x80be0000 // The applications do not have compatible protocol versions.
 #define UA_STATUSCODE_BADCONFIGURATIONERROR 0x80890000 // There is a problem with the configuration that affects the usefulness of the value.
-#define UA_STATUSCODE_BADNOTCONNECTED 0x808a0000 // The variable should receive its value from another variable but has never been configured to do so.
+#define UA_STATUSCODE_BADNOTCONNECTED 0x808a0000 // The variable should receive its value from another variable
 #define UA_STATUSCODE_BADDEVICEFAILURE 0x808b0000 // There has been a failure in the device/data source that generates the value that has affected the value.
 #define UA_STATUSCODE_BADSENSORFAILURE 0x808c0000 // There has been a failure in the sensor from which the value is derived by the device/data source.
 #define UA_STATUSCODE_BADOUTOFSERVICE 0x808d0000 // The source of the data is not operational.
@@ -274,10 +277,10 @@ typedef enum {
 #define UA_STATUSCODE_UNCERTAINENGINEERINGUNITSEXCEEDED 0x40940000 // The value is outside of the range of values defined for this parameter.
 #define UA_STATUSCODE_UNCERTAINSUBNORMAL 0x40950000 // The value is derived from multiple sources and has less than the required number of Good sources.
 #define UA_STATUSCODE_GOODLOCALOVERRIDE 0x00960000 // The value has been overridden.
-#define UA_STATUSCODE_BADREFRESHINPROGRESS 0x80970000 // This Condition refresh failed a Condition refresh operation is already in progress.
+#define UA_STATUSCODE_BADREFRESHINPROGRESS 0x80970000 // This Condition refresh failed
 #define UA_STATUSCODE_BADCONDITIONALREADYDISABLED 0x80980000 // This condition has already been disabled.
 #define UA_STATUSCODE_BADCONDITIONALREADYENABLED 0x80cc0000 // This condition has already been enabled.
-#define UA_STATUSCODE_BADCONDITIONDISABLED 0x80990000 // Property not available this condition is disabled.
+#define UA_STATUSCODE_BADCONDITIONDISABLED 0x80990000 // Property not available
 #define UA_STATUSCODE_BADEVENTIDUNKNOWN 0x809a0000 // The specified event id is not recognized.
 #define UA_STATUSCODE_BADEVENTNOTACKNOWLEDGEABLE 0x80bb0000 // The event cannot be acknowledged.
 #define UA_STATUSCODE_BADDIALOGNOTACTIVE 0x80cd0000 // The dialog condition is not active.
@@ -291,7 +294,7 @@ typedef enum {
 #define UA_STATUSCODE_BADBOUNDNOTFOUND 0x80d70000 // No data found to provide upper or lower bound value.
 #define UA_STATUSCODE_BADBOUNDNOTSUPPORTED 0x80d80000 // The server cannot retrieve a bound for the variable.
 #define UA_STATUSCODE_BADDATALOST 0x809d0000 // Data is missing due to collection started/stopped/lost.
-#define UA_STATUSCODE_BADDATAUNAVAILABLE 0x809e0000 // Expected data is unavailable for the requested time range due to an un-mounted volume, an off-line archive or tape or similar reason for temporary unavailability.
+#define UA_STATUSCODE_BADDATAUNAVAILABLE 0x809e0000 // Expected data is unavailable for the requested time range due to an un-mounted volume
 #define UA_STATUSCODE_BADENTRYEXISTS 0x809f0000 // The data or event was not successfully inserted because a matching entry exists.
 #define UA_STATUSCODE_BADNOENTRYEXISTS 0x80a00000 // The data or event was not successfully updated because no matching entry exists.
 #define UA_STATUSCODE_BADTIMESTAMPNOTSUPPORTED 0x80a10000 // The client requested history using a timestamp format the server does not support (i.e requested ServerTimestamp when server only supports SourceTimestamp).
@@ -304,7 +307,15 @@ typedef enum {
 #define UA_STATUSCODE_BADAGGREGATENOTSUPPORTED 0x80d50000 // The requested Aggregate is not support by the server.
 #define UA_STATUSCODE_BADAGGREGATEINVALIDINPUTS 0x80d60000 // The aggregate value could not be derived due to invalid data inputs.
 #define UA_STATUSCODE_BADAGGREGATECONFIGURATIONREJECTED 0x80da0000 // The aggregate configuration is not valid for specified node.
-#define UA_STATUSCODE_GOODDATAIGNORED 0x00d90000 // The request specifies fields which are not valid for the EventType or cannot be saved by the historian.
+#define UA_STATUSCODE_GOODDATAIGNORED 0x00d90000 // The request pecifies fields which are not valid for the EventType or cannot be saved by the historian.
+#define UA_STATUSCODE_BADREQUESTNOTALLOWED 0x80e40000 // The request was rejected by the server because it did not meet the criteria set by the server.
+#define UA_STATUSCODE_GOODEDITED 0x00dc0000 // The value does not come from the real source and has been edited by the server.
+#define UA_STATUSCODE_GOODPOSTACTIONFAILED 0x00dd0000 // There was an error in execution of these post-actions.
+#define UA_STATUSCODE_UNCERTAINDOMINANTVALUECHANGED 0x40de0000 // The related EngineeringUnit has been changed but the Variable Value is still provided based on the previous unit.
+#define UA_STATUSCODE_GOODDEPENDENTVALUECHANGED 0x00e00000 // A dependent value has been changed but the change has not been applied to the device.
+#define UA_STATUSCODE_BADDOMINANTVALUECHANGED 0x80e10000 // The related EngineeringUnit has been changed but this change has not been applied to the device. The Variable Value is still dependent on the previous unit but its status is currently Bad.
+#define UA_STATUSCODE_UNCERTAINDEPENDENTVALUECHANGED 0x40e20000 // A dependent value has been changed but the change has not been applied to the device. The quality of the dominant variable is uncertain.
+#define UA_STATUSCODE_BADDEPENDENTVALUECHANGED 0x80e30000 // A dependent value has been changed but the change has not been applied to the device. The quality of the dominant variable is Bad.
 #define UA_STATUSCODE_GOODCOMMUNICATIONEVENT 0x00a70000 // The communication layer has raised an event.
 #define UA_STATUSCODE_GOODSHUTDOWNEVENT 0x00a80000 // The system is shutting down.
 #define UA_STATUSCODE_GOODCALLAGAIN 0x00a90000 // The operation is not finished and needs to be called again.
@@ -313,7 +324,7 @@ typedef enum {
 #define UA_STATUSCODE_BADCONNECTIONREJECTED 0x80ac0000 // Could not establish a network connection to remote server.
 #define UA_STATUSCODE_BADDISCONNECT 0x80ad0000 // The server has disconnected from the client.
 #define UA_STATUSCODE_BADCONNECTIONCLOSED 0x80ae0000 // The network connection has been closed.
-#define UA_STATUSCODE_BADINVALIDSTATE 0x80af0000 // The operation cannot be completed because the object is closed uninitialized or in some other invalid state.
+#define UA_STATUSCODE_BADINVALIDSTATE 0x80af0000 // The operation cannot be completed because the object is closed
 #define UA_STATUSCODE_BADENDOFSTREAM 0x80b00000 // Cannot move beyond end of the stream.
 #define UA_STATUSCODE_BADNODATAAVAILABLE 0x80b10000 // No data is currently available for reading from a non-blocking stream.
 #define UA_STATUSCODE_BADWAITINGFORRESPONSE 0x80b20000 // The asynchronous operation is waiting for a response.

+ 44 - 0
include/ua_statuscode_msg.h

@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 the contributors as stated in the AUTHORS file
+ *
+ * This file is part of open62541. open62541 is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU Lesser General
+ * Public License, version 3 (as published by the Free Software Foundation) with
+ * a static linking exception as stated in the LICENSE file provided with
+ * open62541.
+ *
+ * open62541 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ */
+
+#ifndef UA_STATUSCODE_MSG_H_
+#define UA_STATUSCODE_MSG_H_
+
+#include "ua_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct UA_StatusCode_msg_info {
+	UA_StatusCode value;        /* The numeric value from UA_StatusCode */
+	const char* name;    /* The equivalent symbolic value */
+	const char* msg;    /* Short message about this value */
+};
+
+extern const struct UA_StatusCode_msg_info UA_StatusCode_msg_table[];
+
+extern const unsigned int UA_StatusCode_msg_table_size;
+
+UA_EXPORT const char * UA_StatusCode_msg(UA_StatusCode code);
+UA_EXPORT const char * UA_StatusCode_name(UA_StatusCode code);
+UA_StatusCode UA_EXPORT UA_StatusCode_from_name(const char* name);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UA_STATUSCODE_MSG_H_ */

+ 60 - 0
src/ua_statuscode_msg.c

@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 the contributors as stated in the AUTHORS file
+ *
+ * This file is part of open62541. open62541 is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU Lesser General
+ * Public License, version 3 (as published by the Free Software Foundation) with
+ * a static linking exception as stated in the LICENSE file provided with
+ * open62541.
+ *
+ * open62541 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ */
+
+#include "ua_config.h"
+#include "ua_statuscode_msg.h"
+#include "ua_util.h"
+
+/*
+
+ From generated file:
+
+static const struct UA_StatusCode_msg_info UA_StatusCode_msg_table[] =
+{
+		{UA_STATUSCODE_GOOD, "EPERM", "Not owner"},
+		{UA_STATUSCODE_BADINVALIDARGUMENT, "EPERM", "Not owner"},
+		{UA_STATUSCODE_BADOUTOFMEMORY, "EPERM", "Not owner"}
+};
+
+static const unsigned int UA_StatusCode_msg_table_size = 0;
+ */
+
+UA_EXPORT const char* UA_StatusCode_msg(UA_StatusCode code) {
+	for (unsigned int i=0; i<UA_StatusCode_msg_table_size; i++) {
+		if (UA_StatusCode_msg_table[i].value == code)
+			return UA_StatusCode_msg_table[i].msg;
+	}
+	return NULL;
+}
+
+
+UA_EXPORT const char* UA_StatusCode_name(UA_StatusCode code) {
+	for (unsigned int i=0; i<UA_StatusCode_msg_table_size; i++) {
+		if (UA_StatusCode_msg_table[i].value == code)
+			return UA_StatusCode_msg_table[i].name;
+	}
+	return NULL;
+}
+
+
+UA_StatusCode UA_EXPORT UA_StatusCode_from_name(const char* name) {
+	if (name != NULL) {
+		for (unsigned int i=0; i<UA_StatusCode_msg_table_size; i++) {
+			if (strcmp(UA_StatusCode_msg_table[i].name, name) == 0)
+				return UA_StatusCode_msg_table[i].value;
+		}
+	}
+	return UA_UINT32_MAX;
+}

+ 27 - 0
tests/check_utils.c

@@ -2,6 +2,7 @@
 
 #include "ua_types.h"
 #include "ua_client.h"
+#include "ua_statuscode_msg.h"
 #include "check.h"
 
 START_TEST(EndpointUrl_split) {
@@ -112,6 +113,31 @@ START_TEST(readNumber) {
 }
 END_TEST
 
+
+START_TEST(StatusCode_msg) {
+		// first element in table
+    ck_assert_str_eq(UA_StatusCode_msg(UA_STATUSCODE_GOOD), "No error");
+    ck_assert_str_eq(UA_StatusCode_name(UA_STATUSCODE_GOOD), "Good");
+
+
+		// just some randomly picked status codes
+    ck_assert_str_eq(UA_StatusCode_msg(UA_STATUSCODE_BADNOCOMMUNICATION), "Communication with the data source is defined");
+    ck_assert_str_eq(UA_StatusCode_name(UA_STATUSCODE_BADNOCOMMUNICATION), "BadNoCommunication");
+
+    ck_assert_str_eq(UA_StatusCode_msg(UA_STATUSCODE_GOODNODATA), "No data exists for the requested time range or event filter.");
+    ck_assert_str_eq(UA_StatusCode_name(UA_STATUSCODE_GOODNODATA), "GoodNoData");
+
+		// last element in table
+    ck_assert_str_eq(UA_StatusCode_msg(UA_STATUSCODE_BADMAXCONNECTIONSREACHED), "The operation could not be finished because all available connections are in use.");
+    ck_assert_str_eq(UA_StatusCode_name(UA_STATUSCODE_BADMAXCONNECTIONSREACHED), "BadMaxConnectionsReached");
+
+		// an invalid status code
+	ck_assert_ptr_eq(UA_StatusCode_msg(0x80123456), NULL);
+	ck_assert_ptr_eq(UA_StatusCode_name(0x80123456), NULL);
+
+}
+END_TEST
+
 static Suite* testSuite_Utils(void) {
     Suite *s = suite_create("Utils");
     TCase *tc_endpointUrl_split = tcase_create("EndpointUrl_split");
@@ -119,6 +145,7 @@ static Suite* testSuite_Utils(void) {
     suite_add_tcase(s,tc_endpointUrl_split);
     TCase *tc_utils = tcase_create("Utils");
     tcase_add_test(tc_utils, readNumber);
+    tcase_add_test(tc_utils, StatusCode_msg);
     suite_add_tcase(s,tc_utils);
     return s;
 }

+ 51 - 0
tools/generate_statuscode_msg.py

@@ -0,0 +1,51 @@
+from __future__ import print_function
+import sys
+import platform
+import getpass
+import time
+import argparse
+
+parser = argparse.ArgumentParser()
+parser.add_argument('statuscodes', help='path/to/Opc.Ua.StatusCodes.csv')
+parser.add_argument('outfile', help='outfile w/o extension')
+args = parser.parse_args()
+
+f = open(args.statuscodes)
+input_str = f.read()
+f.close()
+input_str = input_str.replace('\r','')
+rows = map(lambda x:tuple(x.split(',')), input_str.split('\n'))
+
+fh = open(args.outfile + ".c",'w')
+def printh(string):
+    print(string, end='\n', file=fh)
+
+printh('''/**********************************************************
+ * '''+args.outfile+'''.hgen -- do not modify
+ **********************************************************
+ * Generated from '''+args.statuscodes+''' with script '''+sys.argv[0]+'''
+ * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser()+''' at '''+
+       time.strftime("%Y-%m-%d %I:%M:%S")+'''
+ **********************************************************/\n
+
+#include "ua_statuscode_msg.h"
+
+const struct UA_StatusCode_msg_info UA_StatusCode_msg_table[] =
+{''')
+
+#for row in rows:
+#    printh("#define UA_STATUSCODE_%s %s // %s" % (row[0].upper(), row[1].lower(), row[2]))
+
+count = 1
+printh(" {UA_STATUSCODE_GOOD, \"Good\", \"No error\"},")
+
+for row in rows:
+    printh(" {UA_STATUSCODE_%s, \"%s\", \"%s\"}," % (row[0].upper(), row[0], row[2]))
+    count += 1
+
+printh('\n};\n')
+
+printh('const unsigned int UA_StatusCode_msg_table_size = ' + str(count) + ';')
+
+
+fh.close()

+ 227 - 0
tools/schema/Opc.Ua.StatusCodes.csv

@@ -0,0 +1,227 @@
+BadUnexpectedError,0x80010000,An unexpected error occurred.
+BadInternalError,0x80020000,An internal error occurred as a result of a programming or configuration error.
+BadOutOfMemory,0x80030000,Not enough memory to complete the operation.
+BadResourceUnavailable,0x80040000,An operating system resource is not available.
+BadCommunicationError,0x80050000,A low level communication error occurred.
+BadEncodingError,0x80060000,Encoding halted because of invalid data in the objects being serialized.
+BadDecodingError,0x80070000,Decoding halted because of invalid data in the stream.
+BadEncodingLimitsExceeded,0x80080000,The message encoding/decoding limits imposed by the stack have been exceeded.
+BadRequestTooLarge,0x80B80000,The request message size exceeds limits set by the server.
+BadResponseTooLarge,0x80B90000,The response message size exceeds limits set by the client.
+BadUnknownResponse,0x80090000,An unrecognized response was received from the server.
+BadTimeout,0x800A0000,The operation timed out.
+BadServiceUnsupported,0x800B0000,The server does not support the requested service.
+BadShutdown,0x800C0000,The operation was cancelled because the application is shutting down.
+BadServerNotConnected,0x800D0000,The operation could not complete because the client is not connected to the server.
+BadServerHalted,0x800E0000,The server has stopped and cannot process any requests.
+BadNothingToDo,0x800F0000,There was nothing to do because the client passed a list of operations with no elements.
+BadTooManyOperations,0x80100000,The request could not be processed because it specified too many operations.
+BadTooManyMonitoredItems,0x80DB0000,The request could not be processed because there are too many monitored items in the subscription.
+BadDataTypeIdUnknown,0x80110000,The extension object cannot be (de)serialized because the data type id is not recognized.
+BadCertificateInvalid,0x80120000,The certificate provided as a parameter is not valid.
+BadSecurityChecksFailed,0x80130000,An error occurred verifying security.
+BadCertificateTimeInvalid,0x80140000,The Certificate has expired or is not yet valid.
+BadCertificateIssuerTimeInvalid,0x80150000,An Issuer Certificate has expired or is not yet valid.
+BadCertificateHostNameInvalid,0x80160000,The HostName used to connect to a Server does not match a HostName in the Certificate.
+BadCertificateUriInvalid,0x80170000,The URI specified in the ApplicationDescription does not match the URI in the Certificate.
+BadCertificateUseNotAllowed,0x80180000,The Certificate may not be used for the requested operation.
+BadCertificateIssuerUseNotAllowed,0x80190000,The Issuer Certificate may not be used for the requested operation.
+BadCertificateUntrusted,0x801A0000,The Certificate is not trusted.
+BadCertificateRevocationUnknown,0x801B0000,It was not possible to determine if the Certificate has been revoked.
+BadCertificateIssuerRevocationUnknown,0x801C0000,It was not possible to determine if the Issuer Certificate has been revoked.
+BadCertificateRevoked,0x801D0000,The certificate has been revoked.
+BadCertificateIssuerRevoked,0x801E0000,The issuer certificate has been revoked.
+BadCertificateChainIncomplete,0x810D0000,The certificate chain is incomplete.
+BadUserAccessDenied,0x801F0000,User does not have permission to perform the requested operation.
+BadIdentityTokenInvalid,0x80200000,The user identity token is not valid.
+BadIdentityTokenRejected,0x80210000,The user identity token is valid but the server has rejected it.
+BadSecureChannelIdInvalid,0x80220000,The specified secure channel is no longer valid.
+BadInvalidTimestamp,0x80230000,The timestamp is outside the range allowed by the server.
+BadNonceInvalid,0x80240000,The nonce does appear to be not a random value or it is not the correct length.
+BadSessionIdInvalid,0x80250000,The session id is not valid.
+BadSessionClosed,0x80260000,The session was closed by the client.
+BadSessionNotActivated,0x80270000,The session cannot be used because ActivateSession has not been called.
+BadSubscriptionIdInvalid,0x80280000,The subscription id is not valid.
+BadRequestHeaderInvalid,0x802A0000,The header for the request is missing or invalid.
+BadTimestampsToReturnInvalid,0x802B0000,The timestamps to return parameter is invalid.
+BadRequestCancelledByClient,0x802C0000,The request was cancelled by the client.
+BadTooManyArguments,0x80E50000,Too many arguments were provided.
+GoodSubscriptionTransferred,0x002D0000,The subscription was transferred to another session.
+GoodCompletesAsynchronously,0x002E0000,The processing will complete asynchronously.
+GoodOverload,0x002F0000,Sampling has slowed down due to resource limitations.
+GoodClamped,0x00300000,The value written was accepted but was clamped.
+BadNoCommunication,0x80310000,Communication with the data source is defined, but not established, and there is no last known value available.
+BadWaitingForInitialData,0x80320000,Waiting for the server to obtain values from the underlying data source.
+BadNodeIdInvalid,0x80330000,The syntax of the node id is not valid.
+BadNodeIdUnknown,0x80340000,The node id refers to a node that does not exist in the server address space.
+BadAttributeIdInvalid,0x80350000,The attribute is not supported for the specified Node.
+BadIndexRangeInvalid,0x80360000,The syntax of the index range parameter is invalid.
+BadIndexRangeNoData,0x80370000,No data exists within the range of indexes specified.
+BadDataEncodingInvalid,0x80380000,The data encoding is invalid.
+BadDataEncodingUnsupported,0x80390000,The server does not support the requested data encoding for the node.
+BadNotReadable,0x803A0000,The access level does not allow reading or subscribing to the Node.
+BadNotWritable,0x803B0000,The access level does not allow writing to the Node.
+BadOutOfRange,0x803C0000,The value was out of range.
+BadNotSupported,0x803D0000,The requested operation is not supported.
+BadNotFound,0x803E0000,A requested item was not found or a search operation ended without success.
+BadObjectDeleted,0x803F0000,The object cannot be used because it has been deleted.
+BadNotImplemented,0x80400000,Requested operation is not implemented.
+BadMonitoringModeInvalid,0x80410000,The monitoring mode is invalid.
+BadMonitoredItemIdInvalid,0x80420000,The monitoring item id does not refer to a valid monitored item.
+BadMonitoredItemFilterInvalid,0x80430000,The monitored item filter parameter is not valid.
+BadMonitoredItemFilterUnsupported,0x80440000,The server does not support the requested monitored item filter.
+BadFilterNotAllowed,0x80450000,A monitoring filter cannot be used in combination with the attribute specified.
+BadStructureMissing,0x80460000,A mandatory structured parameter was missing or null.
+BadEventFilterInvalid,0x80470000,The event filter is not valid.
+BadContentFilterInvalid,0x80480000,The content filter is not valid.
+BadFilterOperatorInvalid,0x80C10000,An unregognized operator was provided in a filter.
+BadFilterOperatorUnsupported,0x80C20000,A valid operator was provided, but the server does not provide support for this filter operator.
+BadFilterOperandCountMismatch,0x80C30000,The number of operands provided for the filter operator was less then expected for the operand provided.
+BadFilterOperandInvalid,0x80490000,The operand used in a content filter is not valid.
+BadFilterElementInvalid,0x80C40000,The referenced element is not a valid element in the content filter.
+BadFilterLiteralInvalid,0x80C50000,The referenced literal is not a valid value.
+BadContinuationPointInvalid,0x804A0000,The continuation point provide is longer valid.
+BadNoContinuationPoints,0x804B0000,The operation could not be processed because all continuation points have been allocated.
+BadReferenceTypeIdInvalid,0x804C0000,The operation could not be processed because all continuation points have been allocated.
+BadBrowseDirectionInvalid,0x804D0000,The browse direction is not valid.
+BadNodeNotInView,0x804E0000,The node is not part of the view.
+BadServerUriInvalid,0x804F0000,The ServerUri is not a valid URI.
+BadServerNameMissing,0x80500000,No ServerName was specified.
+BadDiscoveryUrlMissing,0x80510000,No DiscoveryUrl was specified.
+BadSempahoreFileMissing,0x80520000,The semaphore file specified by the client is not valid.
+BadRequestTypeInvalid,0x80530000,The security token request type is not valid.
+BadSecurityModeRejected,0x80540000,The security mode does not meet the requirements set by the Server.
+BadSecurityPolicyRejected,0x80550000,The security policy does not meet the requirements set by the Server.
+BadTooManySessions,0x80560000,The server has reached its maximum number of sessions.
+BadUserSignatureInvalid,0x80570000,The user token signature is missing or invalid.
+BadApplicationSignatureInvalid,0x80580000,The signature generated with the client certificate is missing or invalid.
+BadNoValidCertificates,0x80590000,The client did not provide at least one software certificate that is valid and meets the profile requirements for the server.
+BadIdentityChangeNotSupported,0x80C60000,The Server does not support changing the user identity assigned to the session.
+BadRequestCancelledByRequest,0x805A0000,The request was cancelled by the client with the Cancel service.
+BadParentNodeIdInvalid,0x805B0000,The parent node id does not to refer to a valid node.
+BadReferenceNotAllowed,0x805C0000,The reference could not be created because it violates constraints imposed by the data model.
+BadNodeIdRejected,0x805D0000,The requested node id was reject because it was either invalid or server does not allow node ids to be specified by the client.
+BadNodeIdExists,0x805E0000,The requested node id is already used by another node.
+BadNodeClassInvalid,0x805F0000,The node class is not valid.
+BadBrowseNameInvalid,0x80600000,The browse name is invalid.
+BadBrowseNameDuplicated,0x80610000,The browse name is not unique among nodes that share the same relationship with the parent.
+BadNodeAttributesInvalid,0x80620000,The node attributes are not valid for the node class.
+BadTypeDefinitionInvalid,0x80630000,The type definition node id does not reference an appropriate type node.
+BadSourceNodeIdInvalid,0x80640000,The source node id does not reference a valid node.
+BadTargetNodeIdInvalid,0x80650000,The target node id does not reference a valid node.
+BadDuplicateReferenceNotAllowed,0x80660000,The reference type between the nodes is already defined.
+BadInvalidSelfReference,0x80670000,The server does not allow this type of self reference on this node.
+BadReferenceLocalOnly,0x80680000,The reference type is not valid for a reference to a remote server.
+BadNoDeleteRights,0x80690000,The server will not allow the node to be deleted.
+UncertainReferenceNotDeleted,0x40BC0000,The server was not able to delete all target references.
+BadServerIndexInvalid,0x806A0000,The server index is not valid.
+BadViewIdUnknown,0x806B0000,The view id does not refer to a valid view node.
+BadViewTimestampInvalid,0x80C90000,The view timestamp is not available or not supported.
+BadViewParameterMismatch,0x80CA0000,The view parameters are not consistent with each other.
+BadViewVersionInvalid,0x80CB0000,The view version is not available or not supported.
+UncertainNotAllNodesAvailable,0x40C00000,The list of references may not be complete because the underlying system is not available.
+GoodResultsMayBeIncomplete,0x00BA0000,The server should have followed a reference to a node in a remote server but did not. The result set may be incomplete.
+BadNotTypeDefinition,0x80C80000,The provided Nodeid was not a type definition nodeid.
+UncertainReferenceOutOfServer,0x406C0000,One of the references to follow in the relative path references to a node in the address space in another server.
+BadTooManyMatches,0x806D0000,The requested operation has too many matches to return.
+BadQueryTooComplex,0x806E0000,The requested operation requires too many resources in the server.
+BadNoMatch,0x806F0000,The requested operation has no match to return.
+BadMaxAgeInvalid,0x80700000,The max age parameter is invalid.
+BadSecurityModeInsufficient,0x80E60000,The operation is not permitted over the current secure channel.
+BadHistoryOperationInvalid,0x80710000,The history details parameter is not valid.
+BadHistoryOperationUnsupported,0x80720000,The server does not support the requested operation.
+BadInvalidTimestampArgument,0x80BD0000,The defined timestamp to return was invalid.
+BadWriteNotSupported,0x80730000,The server not does support writing the combination of value, status and timestamps provided.
+BadTypeMismatch,0x80740000,The value supplied for the attribute is not of the same type as the attribute's value.
+BadMethodInvalid,0x80750000,The method id does not refer to a method for the specified object.
+BadArgumentsMissing,0x80760000,The client did not specify all of the input arguments for the method.
+BadTooManySubscriptions,0x80770000,The server has reached its  maximum number of subscriptions.
+BadTooManyPublishRequests,0x80780000,The server has reached the maximum number of queued publish requests.
+BadNoSubscription,0x80790000,There is no subscription available for this session.
+BadSequenceNumberUnknown,0x807A0000,The sequence number is unknown to the server.
+BadMessageNotAvailable,0x807B0000,The requested notification message is no longer available.
+BadInsufficientClientProfile,0x807C0000,The Client of the current Session does not support one or more Profiles that are necessary for the Subscription.
+BadStateNotActive,0x80BF0000,The sub-state machine is not currently active.
+BadTcpServerTooBusy,0x807D0000,The server cannot process the request because it is too busy.
+BadTcpMessageTypeInvalid,0x807E0000,The type of the message specified in the header invalid.
+BadTcpSecureChannelUnknown,0x807F0000,The SecureChannelId and/or TokenId are not currently in use.
+BadTcpMessageTooLarge,0x80800000,The size of the message specified in the header is too large.
+BadTcpNotEnoughResources,0x80810000,There are not enough resources to process the request.
+BadTcpInternalError,0x80820000,An internal error occurred.
+BadTcpEndpointUrlInvalid,0x80830000,The Server does not recognize the QueryString specified.
+BadRequestInterrupted,0x80840000,The request could not be sent because of a network interruption.
+BadRequestTimeout,0x80850000,Timeout occurred while processing the request.
+BadSecureChannelClosed,0x80860000,The secure channel has been closed.
+BadSecureChannelTokenUnknown,0x80870000,The token has expired or is not recognized.
+BadSequenceNumberInvalid,0x80880000,The sequence number is not valid.
+BadProtocolVersionUnsupported,0x80BE0000,The applications do not have compatible protocol versions.
+BadConfigurationError,0x80890000,There is a problem with the configuration that affects the usefulness of the value.
+BadNotConnected,0x808A0000,The variable should receive its value from another variable, but has never been configured to do so.
+BadDeviceFailure,0x808B0000,There has been a failure in the device/data source that generates the value that has affected the value.
+BadSensorFailure,0x808C0000,There has been a failure in the sensor from which the value is derived by the device/data source.
+BadOutOfService,0x808D0000,The source of the data is not operational.
+BadDeadbandFilterInvalid,0x808E0000,The deadband filter is not valid.
+UncertainNoCommunicationLastUsableValue,0x408F0000,Communication to the data source has failed. The variable value is the last value that had a good quality.
+UncertainLastUsableValue,0x40900000,Whatever was updating this value has stopped doing so.
+UncertainSubstituteValue,0x40910000,The value is an operational value that was manually overwritten.
+UncertainInitialValue,0x40920000,The value is an initial value for a variable that normally receives its value from another variable.
+UncertainSensorNotAccurate,0x40930000,The value is at one of the sensor limits.
+UncertainEngineeringUnitsExceeded,0x40940000,The value is outside of the range of values defined for this parameter.
+UncertainSubNormal,0x40950000,The value is derived from multiple sources and has less than the required number of Good sources.
+GoodLocalOverride,0x00960000,The value has been overridden.
+BadRefreshInProgress,0x80970000,This Condition refresh failed, a Condition refresh operation is already in progress.
+BadConditionAlreadyDisabled,0x80980000,This condition has already been disabled.
+BadConditionAlreadyEnabled,0x80CC0000,This condition has already been enabled.
+BadConditionDisabled,0x80990000,Property not available, this condition is disabled.
+BadEventIdUnknown,0x809A0000,The specified event id is not recognized.
+BadEventNotAcknowledgeable,0x80BB0000,The event cannot be acknowledged.
+BadDialogNotActive,0x80CD0000,The dialog condition is not active.
+BadDialogResponseInvalid,0x80CE0000,The response is not valid for the dialog.
+BadConditionBranchAlreadyAcked,0x80CF0000,The condition branch has already been acknowledged.
+BadConditionBranchAlreadyConfirmed,0x80D00000,The condition branch has already been confirmed.
+BadConditionAlreadyShelved,0x80D10000,The condition has already been shelved.
+BadConditionNotShelved,0x80D20000,The condition is not currently shelved.
+BadShelvingTimeOutOfRange,0x80D30000,The shelving time not within an acceptable range.
+BadNoData,0x809B0000,No data exists for the requested time range or event filter.
+BadBoundNotFound,0x80D70000,No data found to provide upper or lower bound value.
+BadBoundNotSupported,0x80D80000,The server cannot retrieve a bound for the variable.
+BadDataLost,0x809D0000,Data is missing due to collection started/stopped/lost.
+BadDataUnavailable,0x809E0000,Expected data is unavailable for the requested time range due to an un-mounted volume, an off-line archive or tape, or similar reason for temporary unavailability.
+BadEntryExists,0x809F0000,The data or event was not successfully inserted because a matching entry exists.
+BadNoEntryExists,0x80A00000,The data or event was not successfully updated because no matching entry exists.
+BadTimestampNotSupported,0x80A10000,The client requested history using a timestamp format the server does not support (i.e requested ServerTimestamp when server only supports SourceTimestamp).
+GoodEntryInserted,0x00A20000,The data or event was successfully inserted into the historical database.
+GoodEntryReplaced,0x00A30000,The data or event field was successfully replaced in the historical database.
+UncertainDataSubNormal,0x40A40000,The value is derived from multiple values and has less than the required number of Good values.
+GoodNoData,0x00A50000,No data exists for the requested time range or event filter.
+GoodMoreData,0x00A60000,The data or event field was successfully replaced in the historical database.
+BadAggregateListMismatch,0x80D40000,The requested number of Aggregates does not match the requested number of NodeIds.
+BadAggregateNotSupported,0x80D50000,The requested Aggregate is not support by the server.
+BadAggregateInvalidInputs,0x80D60000,The aggregate value could not be derived due to invalid data inputs.
+BadAggregateConfigurationRejected,0x80DA0000,The aggregate configuration is not valid for specified node.
+GoodDataIgnored,0x00D90000,The request pecifies fields which are not valid for the EventType or cannot be saved by the historian.
+BadRequestNotAllowed,0x80E40000,The request was rejected by the server because it did not meet the criteria set by the server.
+GoodEdited,0x00DC0000,The value does not come from the real source and has been edited by the server.
+GoodPostActionFailed,0x00DD0000,There was an error in execution of these post-actions.
+UncertainDominantValueChanged,0x40DE0000,The related EngineeringUnit has been changed but the Variable Value is still provided based on the previous unit.
+GoodDependentValueChanged,0x00E00000,A dependent value has been changed but the change has not been applied to the device.
+BadDominantValueChanged,0x80E10000,The related EngineeringUnit has been changed but this change has not been applied to the device. The Variable Value is still dependent on the previous unit but its status is currently Bad.
+UncertainDependentValueChanged,0x40E20000,A dependent value has been changed but the change has not been applied to the device. The quality of the dominant variable is uncertain.
+BadDependentValueChanged,0x80E30000,A dependent value has been changed but the change has not been applied to the device. The quality of the dominant variable is Bad.
+GoodCommunicationEvent,0x00A70000,The communication layer has raised an event.
+GoodShutdownEvent,0x00A80000,The system is shutting down.
+GoodCallAgain,0x00A90000,The operation is not finished and needs to be called again.
+GoodNonCriticalTimeout,0x00AA0000,A non-critical timeout occurred.
+BadInvalidArgument,0x80AB0000,One or more arguments are invalid.
+BadConnectionRejected,0x80AC0000,Could not establish a network connection to remote server.
+BadDisconnect,0x80AD0000,The server has disconnected from the client.
+BadConnectionClosed,0x80AE0000,The network connection has been closed.
+BadInvalidState,0x80AF0000,The operation cannot be completed because the object is closed, uninitialized or in some other invalid state.
+BadEndOfStream,0x80B00000,Cannot move beyond end of the stream.
+BadNoDataAvailable,0x80B10000,No data is currently available for reading from a non-blocking stream.
+BadWaitingForResponse,0x80B20000,The asynchronous operation is waiting for a response.
+BadOperationAbandoned,0x80B30000,The asynchronous operation was abandoned by the caller.
+BadExpectedStreamToBlock,0x80B40000,The stream did not return all data requested (possibly because it is a non-blocking stream).
+BadWouldBlock,0x80B50000,Non blocking behaviour is required and the operation would block.
+BadSyntaxError,0x80B60000,A value had an invalid syntax.
+BadMaxConnectionsReached,0x80B70000,The operation could not be finished because all available connections are in use.

+ 1 - 1
tools/travis/travis_linux_script.sh

@@ -111,7 +111,7 @@ else
     #this run inclides full examples and methodcalls
     echo "Debug build and unit tests (64 bit)"
     mkdir -p build && cd build
-    cmake -DCMAKE_BUILD_TYPE=Debug -DUA_BUILD_EXAMPLES=ON -DUA_BUILD_UNIT_TESTS=ON -DUA_ENABLE_COVERAGE=ON ..
+    cmake -DCMAKE_BUILD_TYPE=Debug -DUA_BUILD_EXAMPLES=ON -DUA_BUILD_UNIT_TESTS=ON -DUA_ENABLE_COVERAGE=ON -DUA_ENABLE_STATUSCODE_MSG=ON ..
     make -j8 && make test ARGS="-V"
     echo "Run valgrind to see if the server leaks memory (just starting up and closing..)"
     (valgrind --leak-check=yes --error-exitcode=3 ./examples/server & export pid=$!; sleep 2; kill -INT $pid; wait $pid);