Browse Source

Merge branch 'master' of github.com:acplt/open62541

Julius Pfrommer 11 years ago
parent
commit
271dfb8319

+ 6 - 1
Makefile.am

@@ -1,10 +1,15 @@
 AM_CFLAGS = -std=c99 -pedantic -pipe -fPIC -fno-exceptions -fstack-protector -Wl,-z,relro -Wl,-z,now -fvisibility=hidden -W -Wall -Wno-unused-parameter -Wno-unused-function -Wno-unused-label -Wpointer-arith -Wformat -Wreturn-type -Wsign-compare -Wmultichar -Wformat-nonliteral -Winit-self -Wuninitialized -Wno-deprecated -Wformat-security -Werror
 if DEBUG
-AM_CFLAGS += -g3 -O0 -DDEBUG=1 -DVERBOSE=1
+AM_CFLAGS += -g3 -O0
 else
 AM_CFLAGS += -O2 
 endif
 
+if COVERAGE
+AM_CFLAGS += --coverage
+AM_LDFLAGS = --coverage
+endif
+
 export GLOBAL_AM_CFLAGS = $(AM_CFLAGS)
 
 SUBS=tool include src

+ 33 - 16
configure.ac

@@ -31,35 +31,52 @@ AM_COND_IF([TARGET_LINUX],
 AC_ARG_ENABLE(debug,
 AS_HELP_STRING([--enable-debug],
                [enable debugging, default: no]),
-			   [case "${enableval}" in
-               		 yes) debug=true ;;
-             		 no)  debug=false ;;
-             		 *)   AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;; esac],
-				[debug=false])
+	[case "${enableval}" in
+        	yes) debug=true, verbose=false ;;
+             	no)  debug=false, verbose=false ;;
+             	verbose) debug=true, verbose=true ;;
+             	*)   AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;; 
+	esac],[debug=false])
 AM_CONDITIONAL(DEBUG, test x"$debug" = x"true")
 AM_COND_IF([DEBUG],
     AC_DEFINE([DEBUG])) #define DEBUG is accessible from pre-processor
 
+AM_CONDITIONAL(VERBOSE, test x"$verbose" = x"true")
+AM_COND_IF([VERBOSE],
+    AC_DEFINE([VERBOSE])) #define VERBOSE is accessible from pre-processor
+
 AC_ARG_ENABLE(multithreading,
 AS_HELP_STRING([--enable-multithreading],
                [enable multithreading, default: yes]),
-			   [case "${enableval}" in
-               		 yes) multithreading=true ;;
-             		 no)  multithreading=false ;;
-             		 *)   AC_MSG_ERROR([bad value ${enableval} for --enable-multithreading]) ;; esac],
-[multithreading=false])
+	[case "${enableval}" in
+		yes) multithreading=true ;;
+		no)  multithreading=false ;;
+		*)   AC_MSG_ERROR([bad value ${enableval} for --enable-multithreading]) ;; 
+	esac],[multithreading=false])
 AM_CONDITIONAL(MULTITHREADING, test x"$multithreading" = x"true")
 AM_COND_IF([MULTITHREADING],
     AC_DEFINE([MULTITHREADING])) #define MULTITHREADING is accessible from pre-processor
 
+AC_ARG_ENABLE(coverage,
+AS_HELP_STRING([--enable-coverage],
+               [enable coverage, default: no]),
+	[case "${enableval}" in
+		yes) coverage=true ;;
+		no)  coverag=false ;;
+		*)   AC_MSG_ERROR([bad value ${enableval} for --enable-coverage]) ;; 
+	esac],[coverage=false])
+AM_CONDITIONAL(COVERAGE, test x"$coverage" = x"true")
+AM_COND_IF([COVERAGE],
+    AC_DEFINE([COVERAGE])) #define MULTITHREADING is accessible from pre-processor
+
 AC_ARG_ENABLE(doxygen,
-	AS_HELP_STRING([--enable-doxygen],
+AS_HELP_STRING([--enable-doxygen],
                [enable doxygen, default: no]),
-			   [case "${enableval}" in
-               		 yes) enabledoxygen=true ;;
-             		 no)  enabledoxygen=false ;;
-             		 *)   AC_MSG_ERROR([bad value ${enableval} for --enable-doxygen]) ;; esac],
-[enabledoxygen=false])
+	[case "${enableval}" in
+		yes) enabledoxygen=true ;;
+		no)  enabledoxygen=false ;;
+             	*)   AC_MSG_ERROR([bad value ${enableval} for --enable-doxygen]) ;; 
+	esac],[enabledoxygen=false])
 
 AM_CONDITIONAL(ENABLE_DOXYGEN, test x"$enabledoxygen" = x"true")
 AC_CHECK_PROGS([DOXYGEN], [doxygen])

+ 10 - 0
examples/src/Makefile.am

@@ -3,17 +3,27 @@ MT_LDADD = -lpthread
 else
 MT_LDADD =
 endif
+if COVERAGE
+COV_LDFLAGS = --coverage
+else
+COV_LDFLAGS = 
+endif
 
 bin_PROGRAMS= $(top_builddir)/bin/exampleServer $(top_builddir)/bin/exampleServerMT $(top_builddir)/bin/exampleServerACPLT
 #__top_builddir__bin_exampleServer_LDFLAGS = -all-static
 __top_builddir__bin_exampleServer_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include $(GLOBAL_AM_CFLAGS)
 __top_builddir__bin_exampleServer_SOURCES = opcuaServer.c networklayer.c
 __top_builddir__bin_exampleServer_LDADD= $(top_builddir)/lib/libopen62541.a $(MT_LDADD)
+__top_builddir__bin_exampleServer_LDFLAGS= $(COV_LDFLAGS)
 
 __top_builddir__bin_exampleServerMT_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include $(GLOBAL_AM_CFLAGS)
 __top_builddir__bin_exampleServerMT_SOURCES = opcuaServerMT.c networklayer.c
 __top_builddir__bin_exampleServerMT_LDADD= $(top_builddir)/lib/libopen62541.a $(MT_LDADD)
+__top_builddir__bin_exampleServerMT_LDFLAGS= $(COV_LDFLAGS)
 
 __top_builddir__bin_exampleServerACPLT_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include $(GLOBAL_AM_CFLAGS)
 __top_builddir__bin_exampleServerACPLT_SOURCES = opcuaServerACPLT.c 
 __top_builddir__bin_exampleServerACPLT_LDADD= $(top_builddir)/lib/libopen62541.a $(MT_LDADD)
+__top_builddir__bin_exampleServerACPLT_LDFLAGS= $(COV_LDFLAGS)
+
+#AM_CFLAGS = $(GLOBAL_AM_CFLAGS)

+ 5 - 1
examples/src/opcuaServer.c

@@ -4,7 +4,7 @@
  Author      :
  Version     :
  Copyright   : Your copyright notice
- Description :
+ Description : lala
  ============================================================================
  */
 
@@ -12,6 +12,7 @@
 #include <stdlib.h>
 
 #include "networklayer.h"
+#include "ua_application.h"
 
 UA_Int32 serverCallback(void * arg) {
 	char *name = (char *) arg;
@@ -21,6 +22,9 @@ UA_Int32 serverCallback(void * arg) {
 
 int main(int argc, char** argv) {
 	NL_data* nl = NL_init(&NL_Description_TcpBinary,16664);
+	// NL_data* nl = NL_init(&NL_Description_TcpBinary,16664,NL_THREADINGTYPE_SINGLE);
+	appMockup_init();
+
 	struct timeval tv = {2, 0}; // 2 seconds
 	NL_msgLoop(nl, &tv,serverCallback,argv[0]);
 }

+ 3 - 0
examples/src/opcuaServerACPLT.c

@@ -151,9 +151,12 @@ void server_run() {
 				server.writeData.length = 0;
 			}
 		}
+		shutdown(newsockfd,2);
 		close(newsockfd);
 		connection.connectionState = connectionState_CLOSED;
 	}
+	shutdown(sockfd,2);
+	close(sockfd);
 }
 
 #endif

+ 3 - 2
src/Makefile.am

@@ -66,8 +66,9 @@ libopen62541_la_SOURCES = opcua.c\
 						ua_services_attribute.c\
 						ua_services_session.c\
 						ua_services_discovery.c\
-						ua_services_securechannel.c
-						ua_services_view.c
+						ua_services_securechannel.c\
+						ua_services_view.c\
+						ua_application.c
 
 #bin_PROGRAMS= $(top_builddir)/bin/open62541.out
 #__top_builddir__bin_libOpen62541_out_SOURCES = opcuaServer.c

+ 2 - 0
src/ua_application.h

@@ -10,4 +10,6 @@ typedef struct Application_T {
 	UA_indexedList_List *namespaces; // each entry is a namespace
 } Application;
 
+extern Application appMockup;
+void appMockup_init();
 #endif

+ 7 - 7
src/ua_basictypes.c

@@ -338,12 +338,12 @@ UA_TYPE_START_DECODEBINARY(UA_Double)
 	mantissa = (mantissa / 256.0 ) + (UA_Double) (src->data[*pos+4] & 0xFF); 	// bits 32-39
 	mantissa = (mantissa / 256.0 ) + (UA_Double) (src->data[*pos+5] & 0xFF); 	// bits 40-47
 	mantissa = (mantissa / 256.0 ) + (UA_Double) (src->data[*pos+6] & 0x0F); 	// bits 48-51
-	printf("mantissa = %f\n", mantissa);
+	DBG_VERBOSE(printf("UA_Double_decodeBinary - mantissa=%f\n", mantissa));
 	UA_UInt32 biasedExponent ;
 	biasedExponent  = (src->data[*pos+6] & 0xF0) >>  4;				// bits 52-55
-	printf("biasedExponent=%d, src=%d\n", biasedExponent,src->data[*pos+6]);
+	DBG_VERBOSE(printf("UA_Double_decodeBinary - biasedExponent52-55=%d, src=%d\n", biasedExponent,src->data[*pos+6]));
 	biasedExponent |= ((UA_UInt32) (src->data[*pos+7] & 0x7F)) <<  4;	// bits 56-62
-	printf("biasedExponent=%d, src=%d\n", biasedExponent,src->data[*pos+7]);
+	DBG_VERBOSE(printf("UA_Double_decodeBinary - biasedExponent56-62=%d, src=%d\n", biasedExponent,src->data[*pos+7]));
 	UA_Double sign = ( src->data[*pos+7] & 0x80 ) ? -1.0 : 1.0; // bit 63
 	if (biasedExponent >= 1023) {
 		*dst = (UA_Double) sign * (1 << (biasedExponent-1023)) * (1.0 + mantissa / 8.0 );
@@ -1294,16 +1294,16 @@ UA_TYPE_START_ENCODEBINARY(UA_Variant)
 UA_TYPE_END_XXCODEBINARY
 UA_Int32 UA_Variant_decodeBinary(UA_ByteString const * src, UA_Int32 *pos, UA_Variant *dst) {
 	UA_Int32 retval = UA_SUCCESS;
-	UA_Int32 ns0Id;
+	UA_Int32 ns0Id, uaIdx;
 
 	retval |= UA_Byte_decodeBinary(src,pos,&(dst->encodingMask));
 	ns0Id = dst->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK;
 
 	// initialize vTable
-	if (UA_toIndex(ns0Id) == UA_ERR_INVALID_VALUE) {
-		return UA_ERR_INVALID_VALUE;
+	if ((uaIdx = UA_toIndex(ns0Id)) < 0) {
+		return uaIdx;
 	} else {
-		dst->vt = &UA_[UA_toIndex(ns0Id)];
+		dst->vt = &UA_[uaIdx];
 	}
 
 	// get size of array

+ 3 - 0
src/ua_services_attribute.c

@@ -33,6 +33,7 @@ static UA_DataValue * service_read_node(Application *app, const UA_ReadValueId *
 	namespace *ns = UA_indexedList_findValue(app->namespaces, id->nodeId.namespace);
 
 	if (ns == UA_NULL) {
+		DBG_VERBOSE(printf("service_read_node - unknown namespace %d\n",id->nodeId.namespace));
 		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
 		v->status = UA_STATUSCODE_BADNODEIDUNKNOWN;
 		return v;
@@ -158,6 +159,8 @@ UA_Int32 Service_Read(SL_Channel *channel, const UA_ReadRequest *request, UA_Rea
 	response->resultsSize = readsize;
 	UA_alloc((void **)&response->results, sizeof(void *)*readsize);
 	for(int i=0;i<readsize;i++) {
+		DBG_VERBOSE(printf("service_read - attributeId=%d\n",request->nodesToRead[i]->attributeId));
+		DBG_VERBOSE(UA_NodeId_printf("service_read - nodeId=",&(request->nodesToRead[i]->nodeId)));
 		response->results[i] = service_read_node(channel->session->application, request->nodesToRead[i]);
 	}
 	response->diagnosticInfosSize = -1;

+ 10 - 1
src/ua_services_session.c

@@ -1,8 +1,15 @@
 #include "ua_services.h"
+#include "ua_application.h"
+
+Session sessionMockup = {
+		(UA_Int32) 0,
+		&appMockup
+};
 
 UA_Int32 Service_CreateSession(SL_Channel *channel, const UA_CreateSessionRequest *request, UA_CreateSessionResponse *response) {
 	UA_String_printf("CreateSession Service - endpointUrl=", &(request->endpointUrl));
 	// FIXME: create session
+
 	response->sessionId.encodingByte = UA_NODEIDTYPE_FOURBYTE;
 	response->sessionId.namespace = 1;
 	response->sessionId.identifier.numeric = 666;
@@ -15,7 +22,9 @@ UA_Int32 Service_ActivateSession(SL_Channel *channel, const UA_ActivateSessionRe
 	// 321 == AnonymousIdentityToken_Encoding_DefaultBinary
 	UA_NodeId_printf("ActivateSession - uIdToken.type=", &(request->userIdentityToken.typeId));
 	UA_ByteString_printx_hex("ActivateSession - uIdToken.body=", &(request->userIdentityToken.body));
-	// FIXME: channel->application = <Application Ptr>
+
+	// FIXME: channel->session->application = <Application Ptr>
+	channel->session = &sessionMockup;
 	return UA_SUCCESS;
 }
 

+ 6 - 4
src/ua_services_view.c

@@ -1,9 +1,11 @@
 #include "ua_services.h"
 
-UA_Int32 Service_Read(SL_Channel *channel, const UA_ReadRequest *request, UA_ReadResponse *response) {
-	UA_NodeId_printf("BrowseService - view=",&(p->view.viewId));
+UA_Int32 Service_Browse(SL_Channel *channel, const UA_BrowseRequest *request, UA_BrowseResponse *response) {
+	UA_Int32 retval = UA_SUCCESS;
+	DBG_VERBOSE(UA_NodeId_printf("BrowseService - view=",&(request->view.viewId)));
 	UA_Int32 i = 0;
-	for (i=0;p->nodesToBrowseSize > 0 && i<p->nodesToBrowseSize;i++) {
-		UA_NodeId_printf("BrowseService - nodesToBrowse=", &(p->nodesToBrowse[i]->nodeId));
+	for (i=0;request->nodesToBrowseSize > 0 && i<request->nodesToBrowseSize;i++) {
+		UA_NodeId_printf("BrowseService - nodesToBrowse=", &(request->nodesToBrowse[i]->nodeId));
 	}
+	return retval;
 }

+ 17 - 4
tests/Makefile.am

@@ -9,18 +9,31 @@ check_PROGRAMS += $(UNIT_TESTS)
 
 TESTS_ENVIRONMENT_MEM="libtool --mode=execute valgrind --leak-check=full --quiet --suppressions=suppressions --gen-suppressions=no --error-exitcode=666"
 
+cov-report:
+	mkdir -p coverage
+	lcov --compat-libtool --directory . --directory ../src --capture --output-file coverage/app.info  
+	genhtml -o coverage/ coverage/app.info 
+
 .PHONY: check-mem
 check-mem:
 	$(MAKE) $(AM_MAKEFLAGS) check TESTS="$(UNIT_TESTS)" TESTS_ENVIRONMENT=$(TESTS_ENVIRONMENT_MEM)
-
+if COVERAGE
+	$(MAKE) cov-report
+endif
+	
 clean-local:
-	rm -rf *.gcda *.gcdo *.gcno 
 	rm -rf coverage || true;
+	rm -rf *.gcda *.gcdo *.gcno 
+	lcov --directory . --zerocounters
+	
 # --- no changes beyond this line needed ---
 INCLUDE = @CHECK_CFLAGS@ -I$(top_builddir)/src -I$(top_builddir)/include
 LDADD = $(top_builddir)/lib/libopen62541.a @CHECK_LIBS@
 
-AM_LDFLAGS = $(LDADD)  --coverage
+AM_LDFLAGS = $(LDADD)
+if COVERAGE
+AM_LDFLAGS += --coverage
+endif
 
-AM_CFLAGS = $(GLOBAL_AM_CFLAGS) $(INCLUDE) --coverage
+AM_CFLAGS = $(GLOBAL_AM_CFLAGS) $(INCLUDE)
 

+ 0 - 2
tests/check_builtin.c

@@ -780,7 +780,6 @@ START_TEST(UA_Double_decodeShallGiveOne)
 	// then
 	ck_assert_int_eq(retval,UA_SUCCESS);
 	ck_assert_int_eq(pos,8);
-	printf("UA_Double_decodeShallGiveOne %f\n",dst);
 	ck_assert(0.9999999 < dst);
 	ck_assert(dst < 1.00000000001);
 }
@@ -797,7 +796,6 @@ START_TEST(UA_Double_decodeShallGiveZero)
 	// then
 	ck_assert_int_eq(retval,UA_SUCCESS);
 	ck_assert_int_eq(pos,8);
-	printf("UA_Double_decodeShallGiveZero %f\n",dst);
 	ck_assert(-0.00000001 < dst);
 	ck_assert(dst < 0.000000001);
 }

+ 63 - 0
tests/check_list.c

@@ -144,6 +144,66 @@ START_TEST(searchElementShallFind24)
 }
 END_TEST
 
+START_TEST(addAndRemoveShallYieldEmptyList)
+{
+	// given
+	UA_list_List list;
+	UA_list_init(&list);
+	UA_Int32 plv[] = {42};
+	myAddPayloadVectorToFront(&list,plv,sizeof(plv)/sizeof(UA_Int32));
+	// when
+	UA_list_Element* e = UA_list_search(&list,comparer,(void*)&plv[0]);
+	UA_list_removeElement(e,UA_NULL);
+	visit_count = 0;
+	UA_list_iteratePayload(&list,visitor);
+	// then
+	ck_assert_int_eq(list.size,0);
+	ck_assert_int_eq(visit_count,0);
+	// finally
+	UA_list_destroy(&list, freer);
+}
+END_TEST
+
+START_TEST(addTwiceAndRemoveFirstShallYieldListWithOneElement)
+{
+	// given
+	UA_list_List list;
+	UA_list_init(&list);
+	UA_Int32 plv[] = {42,24};
+	myAddPayloadVectorToFront(&list,plv,sizeof(plv)/sizeof(UA_Int32));
+	// when
+	UA_list_Element* e = UA_list_search(&list,comparer,(void*)&plv[0]);
+	UA_list_removeElement(e,UA_NULL);
+	visit_count = 0;
+	UA_list_iteratePayload(&list,visitor);
+	// then
+	ck_assert_int_eq(list.size,1);
+	ck_assert_int_eq(visit_count,1);
+	// finally
+	UA_list_destroy(&list, freer);
+}
+END_TEST
+
+START_TEST(addTwiceAndRemoveLastShallYieldListWithOneElement)
+{
+	// given
+	UA_list_List list;
+	UA_list_init(&list);
+	UA_Int32 plv[] = {42,24};
+	myAddPayloadVectorToFront(&list,plv,sizeof(plv)/sizeof(UA_Int32));
+	// when
+	UA_list_Element* e = UA_list_search(&list,comparer,(void*)&plv[1]);
+	UA_list_removeElement(e,UA_NULL);
+	visit_count = 0;
+	UA_list_iteratePayload(&list,visitor);
+	// then
+	ck_assert_int_eq(list.size,1);
+	ck_assert_int_eq(visit_count,1);
+	// finally
+	UA_list_destroy(&list, freer);
+}
+END_TEST
+
 Suite*list_testSuite(void)
 {
 	Suite *s = suite_create("list_test");
@@ -152,6 +212,9 @@ Suite*list_testSuite(void)
 	tcase_add_test(tc_core, addElementsShallResultInRespectiveSize);
 	tcase_add_test(tc_core, findElementShallFind42);
 	tcase_add_test(tc_core, searchElementShallFind24);
+	tcase_add_test(tc_core, addAndRemoveShallYieldEmptyList);
+	tcase_add_test(tc_core, addTwiceAndRemoveFirstShallYieldListWithOneElement);
+	tcase_add_test(tc_core, addTwiceAndRemoveLastShallYieldListWithOneElement);
 	suite_add_tcase(s,tc_core);
 	return s;
 }

+ 35 - 3
tests/check_memory.c

@@ -11,7 +11,7 @@
 #include "opcua.h"
 #include "check.h"
 
-START_TEST (checkEncodeShallYieldDecode)
+START_TEST (encodeShallYieldDecode)
 {
 	void *obj1 = UA_NULL, *obj2 = UA_NULL;
 	UA_ByteString msg1, msg2;
@@ -44,17 +44,49 @@ START_TEST (checkEncodeShallYieldDecode)
 }
 END_TEST
 
+START_TEST (decodeShallFailWithTruncatedBufferButSurvive)
+{
+	void *obj1 = UA_NULL, *obj2 = UA_NULL;
+	UA_ByteString msg1;
+	UA_Int32 retval, pos;
+
+	retval = UA_[_i].new(&obj1);
+	UA_ByteString_newMembers(&msg1,UA_[_i].calcSize(obj1));
+	pos = 0;
+	retval = UA_[_i].encodeBinary(obj1, &pos, &msg1);
+	ck_assert_int_eq(retval,UA_SUCCESS);
+
+	UA_[_i].new(&obj2);
+	pos = 0;
+	msg1.length = msg1.length / 2;
+	retval = UA_[_i].decodeBinary(&msg1, &pos, obj2);
+
+	ck_assert_msg(retval!=UA_SUCCESS,"testing %s with half buffer",UA_[_i].name);
+
+	pos = 0;
+	msg1.length = msg1.length / 4;
+	retval = UA_[_i].decodeBinary(&msg1, &pos, obj2);
+
+	ck_assert_msg(retval!=UA_SUCCESS,"testing %s with quarter buffer",UA_[_i].name);
+
+}
+END_TEST
+
 int main() {
 	int number_failed = 0;
 	SRunner *sr;
 
 	Suite *s = suite_create("testMemoryHandling");
 	TCase *tc = tcase_create("Empty Objects");
-	tcase_add_loop_test(tc, checkEncodeShallYieldDecode,23,UA_INVALIDTYPE-1);
+	tcase_add_loop_test(tc, encodeShallYieldDecode,UA_BOOLEAN,UA_INVALIDTYPE-1);
+	suite_add_tcase(s,tc);
+	tc = tcase_create("Truncated Buffers");
+	tcase_add_loop_test(tc, decodeShallFailWithTruncatedBufferButSurvive,UA_BOOLEAN,UA_INVALIDTYPE-1);
 	suite_add_tcase(s,tc);
 
 	sr = srunner_create(s);
-	srunner_set_fork_status(sr,CK_NOFORK);
+	//for debugging puposes only
+	//srunner_set_fork_status(sr,CK_NOFORK);
 	srunner_run_all(sr,CK_NORMAL);
 	number_failed += srunner_ntests_failed(sr);
 	srunner_free(sr);

+ 54 - 4
tests/check_namespace.c

@@ -24,6 +24,52 @@ START_TEST(test_Namespace) {
 }
 END_TEST
 
+UA_Int32 createNode(UA_Node** p, UA_Int16 nsid, UA_Int32 id) {
+	UA_Node_new(p);
+	(*p)->nodeId.encodingByte = UA_NODEIDTYPE_FOURBYTE;
+	(*p)->nodeId.namespace = nsid;
+	(*p)->nodeId.identifier.numeric = id;
+	return UA_SUCCESS;
+}
+
+START_TEST(findNodeInNamespaceWithSingleEntry) {
+	// given
+	namespace *ns;
+	create_ns(&ns, 512);
+	UA_Node* n1; createNode(&n1,0,2253); insert_node(ns,n1);
+	UA_Node* nr = UA_NULL;
+	ns_lock* nl = UA_NULL;
+	UA_Int32 retval;
+	// when
+	retval = get_node(ns,&(n1->nodeId),&nr,&nl);
+	// then
+	ck_assert_int_eq(retval, UA_SUCCESS);
+	ck_assert_ptr_eq(nr,n1);
+	// finally
+	delete_ns(ns);
+}
+END_TEST
+
+START_TEST(findNodeInNamespaceWithTwoEntries) {
+	// given
+	namespace *ns;
+	create_ns(&ns, 512);
+	UA_Node* n1; createNode(&n1,0,2253); insert_node(ns,n1);
+	UA_Node* n2; createNode(&n2,0,2255); insert_node(ns,n2);
+
+	UA_Node* nr = UA_NULL;
+	ns_lock* nl = UA_NULL;
+	UA_Int32 retval;
+	// when
+	retval = get_node(ns,&(n2->nodeId),&nr,&nl);
+	// then
+	ck_assert_int_eq(retval, UA_SUCCESS);
+	ck_assert_ptr_eq(nr,&n1);
+	// finally
+	delete_ns(ns);
+}
+END_TEST
+
 Suite * namespace_suite (void) {
 	Suite *s = suite_create ("Namespace");
 
@@ -31,17 +77,21 @@ Suite * namespace_suite (void) {
 	tcase_add_test (tc_cd, test_Namespace);
 	suite_add_tcase (s, tc_cd);
 
+	TCase* tc_find = tcase_create ("Find");
+	tcase_add_test (tc_find, findNodeInNamespaceWithSingleEntry);
+	tcase_add_test (tc_find, findNodeInNamespaceWithTwoEntries);
+	suite_add_tcase (s, tc_find);
+
 	return s;
 }
 
 int main (void) {
-	return 0;
-	int number_failed;
+	int number_failed =0;
 	Suite *s = namespace_suite ();
 	SRunner *sr = srunner_create (s);
+	srunner_set_fork_status(sr,CK_NOFORK);
 	srunner_run_all (sr, CK_NORMAL);
-	number_failed = srunner_ntests_failed (sr);
+	number_failed += srunner_ntests_failed (sr);
 	srunner_free (sr);
-	number_failed = 1;
 	return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
 }

+ 1 - 1
tool/generate_namespace.py

@@ -77,7 +77,7 @@ print('''/**********************************************************
 #include "opcua.h"
 
 UA_Int32 UA_toIndex(UA_Int32 id) {
-    UA_Int32 retval = -1;
+    UA_Int32 retval = UA_ERR_INVALID_VALUE;
     switch (id) { ''', end='\n',file=fc)
 
 i = 0