Explorar o código

Merge branch 'master' of https://github.com/Stasik0/Open62541

Conflicts:
	src/opcua_binaryEncDec.c
	src/opcua_secureChannelLayer.c
FlorianPalm %!s(int64=11) %!d(string=hai) anos
pai
achega
aae25eb9f8

+ 1 - 0
.gitignore

@@ -42,3 +42,4 @@ libtool
 coverage_report
 .project
 .cproject
+/INSTALL

+ 33 - 48
src/opcua_binaryEncDec.c

@@ -95,7 +95,6 @@ Int32 encoder_encodeBuiltInDatatype(void *data, Int32 type, Int32 *pos,
 	return UA_NO_ERROR;
 }
 
-
 Int32 decoder_decodeBuiltInDatatype(char const * srcBuf, Int32 type, Int32 *pos,
 		void *dstStructure) {
 	Boolean tmp;
@@ -431,24 +430,16 @@ Int32 decoder_decodeBuiltInDatatype(char const * srcBuf, Int32 type, Int32 *pos,
  }
 
 
-/* not tested */
+ /* not tested */
 /*needs to be reimplemented */
-Int32 encoder_encodeBuiltInDatatypeArray(void *data, Int32 size, Int32 type,
-		Int32 *pos, char *dstBuf)
-{
+Int32 encode_builtInDatatypeArray(void *data, Int32 size, Int32 type,
+		Int32 *pos, char *dstBuf) {
 	int i;
-	void * pItem = NULL;
+	void * pItem;
 	encoder_encodeBuiltInDatatype((void*) (size), INT32, pos, dstBuf);
-	pItem = data;
-	for (i = 0; i < size; i++)
-	{
-		//-128 does the conversion e.g. from BOOLEAN_ARRAY to BOOLEAN (type)
-		encoder_encodeBuiltInDatatype(pItem, type - 128 , pos, dstBuf);
-		pItem++;
-	}
-	/*	switch (type)
-		{
-
+	for (i = 0; i < size;) {
+		encoder_encodeBuiltInDatatype(pItem, type, pos, dstBuf);
+		switch (type) {
 		case BOOLEAN:
 			pItem = (Boolean*) (data) + 1;
 			break;
@@ -526,7 +517,6 @@ Int32 encoder_encodeBuiltInDatatypeArray(void *data, Int32 size, Int32 type,
 			break;
 		}
 	}
-	*/
 	return UA_NO_ERROR;
 }
 
@@ -848,7 +838,6 @@ Int32 encodeUANodeId(UA_NodeId *srcNodeId, Int32 *pos, char *buf) {
 }
 Int32 nodeId_calcSize(UA_NodeId *nodeId) {
 	Int32 length = 0;
-	printf("nodeId_calcSize - nodeId.EncodingByte = %d \n",nodeId->EncodingByte);
 	switch (nodeId->EncodingByte) {
 	case NIEVT_TWO_BYTE:
 		length += 2 * sizeof(Byte);
@@ -874,7 +863,6 @@ Int32 nodeId_calcSize(UA_NodeId *nodeId) {
 	default:
 		break;
 	}
-	printf("nodeId_calcSize - nodeId length = %d \n",length);
 	return length;
 }
 /**
@@ -1155,9 +1143,6 @@ Int32 decodeVariant(char const * buf, Int32 *pos, UA_Variant *dstVariant) {
 		//	dstVariant->Value->
 	}
 
-
-
-
 	//TODO implement the multiarray decoding
 	return UA_NO_ERROR;
 }
@@ -1171,7 +1156,7 @@ Int32 encodeVariant(UA_Variant *variant, Int32 *pos, char *dstBuf) {
 				pos, dstBuf);
 		if (variant->ArrayLength > 0) {
 			//encode array as given by variant type
-			encoder_encodeBuiltInDatatypeArray((void*) variant->Value,
+			encode_builtInDatatypeArray((void*) variant->Value,
 					variant->ArrayLength, (variant->EncodingMask & 31), pos,
 					dstBuf);
 		}
@@ -1412,16 +1397,12 @@ Int32 encodeDiagnosticInfo(UA_DiagnosticInfo *diagnosticInfo, Int32 *pos,
 	return UA_NO_ERROR;
 }
 Int32 diagnosticInfo_calcSize(UA_DiagnosticInfo *diagnosticInfo) {
-	Int32 minimumLength = 1;
-	Int32 length = minimumLength;
+	Int32 length = 0;
 	Byte mask;
-	Int32 j = 0;
-	mask = 0;
 
-	//puts("diagnosticInfo called");
-	//printf("with this mask %u", diagnosticInfo->EncodingMask);
-	for (mask = 1; mask <= 0x40; mask *= 2) {
-		j++;
+	length += sizeof(Byte);	// EncodingMask
+
+	for (mask = 0x01; mask <= 0x40; mask *= 2) {
 		switch (mask & (diagnosticInfo->EncodingMask)) {
 
 		case DIEMT_SYMBOLIC_ID:
@@ -1438,8 +1419,7 @@ Int32 diagnosticInfo_calcSize(UA_DiagnosticInfo *diagnosticInfo) {
 			length += sizeof(Int32);
 			break;
 		case DIEMT_ADDITIONAL_INFO:
-			length += diagnosticInfo->AdditionalInfo.Length;
-			length += sizeof(Int32);
+			length += UAString_calcSize(&(diagnosticInfo->AdditionalInfo));
 			break;
 		case DIEMT_INNER_STATUS_CODE:
 			length += sizeof(UA_StatusCode);
@@ -1471,20 +1451,14 @@ Int32 decoder_decodeRequestHeader(char const * message, Int32 *pos,
 	// requestHeader - common request parameters. The authenticationToken is always omitted
 	decoder_decodeBuiltInDatatype(message, NODE_ID, pos,
 			&(dstRequestHeader->authenticationToken));
-
 	decoder_decodeBuiltInDatatype(message, DATE_TIME, pos,
 			&(dstRequestHeader->timestamp));
 	decoder_decodeBuiltInDatatype(message, UINT32, pos,
 			&(dstRequestHeader->requestHandle));
-
-	//dstRequestHeader->requestHandle = decodeIntegerId(srcRaw->message, pos);
 	decoder_decodeBuiltInDatatype(message, UINT32, pos,
 			&(dstRequestHeader->returnDiagnostics));
-	//dstRequestHeader->returnDiagnostics = decodeUInt32(srcRaw->message, pos);
-
 	decoder_decodeBuiltInDatatype(message, STRING, pos,
 			&(dstRequestHeader->auditEntryId));
-	//decodeUAString(srcRaw->message, pos, &dstRequestHeader->auditEntryId);
 	decoder_decodeBuiltInDatatype(message, UINT32, pos,
 			&(dstRequestHeader->timeoutHint));
 	decoder_decodeBuiltInDatatype(message, EXTENSION_OBJECT, pos,
@@ -1518,26 +1492,37 @@ Int32 extensionObject_calcSize(UA_ExtensionObject *extensionObject) {
 
 	if (extensionObject->Encoding == BODY_IS_BYTE_STRING
 			|| extensionObject->Encoding == BODY_IS_XML_ELEMENT) {
-		length += sizeof(Int32) + extensionObject->Body.Length;
+		length += UAByteString_calcSize(&(extensionObject->Body));
 	}
 	return length;
 }
 
 Int32 responseHeader_calcSize(UA_AD_ResponseHeader *responseHeader) {
-	Int32 minimumLength = 20; // summation of all simple types
-	Int32 i, length;
-	length = minimumLength;
+	Int32 i;
+	Int32 length = 0;
 
-	for (i = 0; i < responseHeader->noOfStringTable; i++) {
-		length += responseHeader->stringTable[i].Length;
-		length += sizeof(UInt32); // length of the encoded length field
-	}
+	// UtcTime timestamp	8
+	length += sizeof(UA_DateTime);
 
+	// IntegerId requestHandle	4
+	length += sizeof(UA_AD_IntegerId);
+
+	// StatusCode serviceResult	4
+	length += sizeof(UA_StatusCode);
+
+	// DiagnosticInfo serviceDiagnostics
 	length += diagnosticInfo_calcSize(responseHeader->serviceDiagnostics);
 
+	// String stringTable[], see 62541-6 § 5.2.4
+	length += sizeof(Int32); // Length of Stringtable always
+	if (responseHeader->noOfStringTable > 0) {
+		for (i = 0; i < responseHeader->noOfStringTable; i++) {
+			length += UAString_calcSize(responseHeader->stringTable[i]);
+		}
+	}
 
+	// ExtensibleObject additionalHeader
 	length += extensionObject_calcSize(responseHeader->additionalHeader);
-
 	return length;
 }
 

+ 2 - 1
src/opcua_builtInDatatypes.c

@@ -4,10 +4,11 @@
  *  Created on: Dec 19, 2013
  *      Author: opcua
  */
-
 #include "opcua_builtInDatatypes.h"
 #include <stdio.h>
 
+UA_ExtensionObject the_empty_UA_ExtensionObject = { { NIEVT_TWO_BYTE, 0 }, NO_BODY_IS_ENCODED};
+
 Int32 UA_String_compare(UA_String *string1, UA_String *string2) {
 	Int32 i;
 	Boolean equal;

+ 3 - 0
src/opcua_builtInDatatypes.h

@@ -400,6 +400,9 @@ typedef enum UA_ExtensionObjectEncodingMaskType
 }
 UA_ExtensionObjectEncodingMaskType;
 
+// the empty extensionobject
+extern UA_ExtensionObject the_empty_UA_ExtensionObject;
+
 typedef UA_VariantUnion;
 /**
 * VariantBinaryEncoding

+ 35 - 30
src/opcua_secureChannelLayer.c

@@ -138,7 +138,11 @@ Int32 SL_openSecureChannel(UA_connection *connection,
 		UA_AD_RequestHeader *requestHeader,
 		UA_StatusCode serviceResult)
 {
+
+
+
 	UA_AD_ResponseHeader responseHeader;
+	UA_ExtensionObject additionalHeader;
 	SL_ChannelSecurityToken securityToken;
 	UA_ByteString serverNonce;
 	UA_NodeId responseType;
@@ -243,6 +247,8 @@ Int32 SL_openSecureChannel(UA_connection *connection,
 	response.Data = (char*)opcua_malloc(sizeResponseType + sizeRespHeader + sizeRespMessage);
 	response.Length = sizeResponseType + sizeRespHeader + sizeRespMessage;
 
+	//get memory for response
+	response.Data = (char*)opcua_malloc(nodeId_calcSize(responseType) + sizeRespHeader + sizeRespMessage);
 	*pos = 0;
 	//encode responseType (NodeId)
 	UA_NodeId_printf("SL_openSecureChannel - TypeId =",&responseType);
@@ -298,6 +304,8 @@ Int32 SL_createSecurityToken(UA_connection *connection, Int32 lifeTime) {
 }
 
 Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
+	UA_DiagnosticInfo serviceDiagnostics;
+
 	Int32 pos = 0;
 	UA_AD_RequestHeader requestHeader;
 	UInt32 clientProtocolVersion;
@@ -318,24 +326,19 @@ Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 			&& serviceRequestType.Identifier.Numeric == 446) {
 		/* OpenSecureChannelService, defined in 62541-6 §6.4.4, Table 34.
 		 * Note that part 6 adds ClientProtocolVersion and ServerProtocolVersion
-		 * to the definition in part 4
-		 *
-		 * Request
-		 *
-		 * 	Req-1) RequestHeader requestHeader
-		 * 	Req-2) UInt32 ClientProtocolVersion
-		 * 	Req-3) Enum SecurityTokenRequestType requestType
-		 * 	Req-4) Enum MessageSecurityMode SecurityMode
-		 *  Req-5) ByteString ClientNonce
-		 *  Req-6) Int32 RequestLifetime
-		 *
-		 * Response
-		 *
-		 * 	Res-1) ResponseHeader responseHeader
-		 * 	Res-2) UInt32 ServerProtocolVersion
-		 * 	Res-3) SecurityToken channelSecurityToken
-		 *  Res-5) ByteString ServerNonce
-		 */
+		 * to the definition in part 4 */
+		// 	Req-1) RequestHeader requestHeader
+		UA_AD_RequestHeader requestHeader;
+		// 	Req-2) UInt32 ClientProtocolVersion
+		UInt32 clientProtocolVersion;
+		// 	Req-3) Enum SecurityTokenRequestType requestType
+		Int32 requestType;
+		// 	Req-4) Enum MessageSecurityMode SecurityMode
+		Int32 securityMode;
+		//  Req-5) ByteString ClientNonce
+		UA_ByteString clientNonce;
+		//  Req-6) Int32 RequestLifetime
+		Int32 requestedLifetime;
 
 		UA_ByteString_printx("SL_processMessage - message=", &message);
 
@@ -350,7 +353,8 @@ Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 		// 	Req-2) UInt32 ClientProtocolVersion
 		decoder_decodeBuiltInDatatype(message.Data, UINT32, &pos,
 				&clientProtocolVersion);
-		printf("SL_processMessage - clientProtocolVersion=%d\n",clientProtocolVersion);
+		printf("SL_processMessage - clientProtocolVersion=%d\n",
+				clientProtocolVersion);
 
 		if (clientProtocolVersion
 				!= connection->transportLayer.remoteConf.protocolVersion) {
@@ -362,7 +366,7 @@ Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 
 		// 	Req-3) SecurityTokenRequestType requestType
 		decoder_decodeBuiltInDatatype(message.Data, INT32, &pos, &requestType);
-		printf("SL_processMessage - requestType=%d\n",requestType);
+		printf("SL_processMessage - requestType=%d\n", requestType);
 		switch (requestType) {
 		case securityToken_ISSUE:
 			if (connection->secureLayer.connectionState
@@ -389,37 +393,38 @@ Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 
 		// 	Req-4) MessageSecurityMode SecurityMode
 		decoder_decodeBuiltInDatatype(message.Data, INT32, &pos, &securityMode);
-		printf("SL_processMessage - securityMode=%d\n",securityMode);
+		printf("SL_processMessage - securityMode=%d\n", securityMode);
 		switch (securityMode) {
 		case securityMode_INVALID:
 			connection->secureLayer.clientNonce.Data = NULL;
 			connection->secureLayer.clientNonce.Length = 0;
 			printf("SL_processMessage - client demands no security \n");
 			break;
+
 		case securityMode_SIGN:
+			printf("SL_processMessage - client demands signed \n");
 			//TODO check if senderCertificate and ReceiverCertificateThumbprint are present
 			break;
 
 		case securityMode_SIGNANDENCRYPT:
+			printf("SL_processMessage - client demands signed & encrypted \n");
 			//TODO check if senderCertificate and ReceiverCertificateThumbprint are present
 			break;
 		}
 
 		//  Req-5) ByteString ClientNonce
-		decoder_decodeBuiltInDatatype(message.Data, BYTE_STRING, &pos, &clientNonce);
-		UA_String_printf("SL_processMessage - clientNonce=",&clientNonce);
+		decoder_decodeBuiltInDatatype(message.Data, BYTE_STRING, &pos,
+				&clientNonce);
+		UA_String_printf("SL_processMessage - clientNonce=", &clientNonce);
 
 		//  Req-6) Int32 RequestLifetime
 		decoder_decodeBuiltInDatatype(message.Data, INT32, &pos,
 				&requestedLifetime);
-		printf("SL_processMessage - requestedLifeTime=%d\n",requestedLifetime);
+		printf("SL_processMessage - requestedLifeTime=%d\n", requestedLifetime);
 		//TODO process requestedLifetime
 
-		//TODO
-		serviceResult = 0;
-
-		SL_openSecureChannel(connection, &requestHeader, serviceResult);
-
+		// 62541-4 §7.27 "The requestHandle given by the Client to the request."
+		return SL_openSecureChannel(connection, requestHeader.requestHandle, SC_Good, &serviceDiagnostics);
 	} else {
 		printf("SL_processMessage - unknown service request");
 		//TODO change error code
@@ -485,7 +490,7 @@ void SL_receive(UA_connection *connection, UA_ByteString *serviceMessage) {
 			printf("SL_receive - SequenceHeader.SequenceNr=%d\n",
 					SequenceHeader.SequenceNumber);
 			//save request id to return it to client
-			connection->secureLayer.requestId= SequenceHeader.RequestId;
+			connection->secureLayer.requestId = SequenceHeader.RequestId;
 			//TODO check that the sequence number is smaller than MaxUInt32 - 1024
 			connection->secureLayer.sequenceNumber =
 					SequenceHeader.SequenceNumber;

+ 2 - 2
src/opcua_types.h

@@ -806,8 +806,8 @@ typedef struct UA_AD_ResponseHeader
 	UA_AD_IntegerId requestHandle;
 	UA_StatusCode serviceResult;
 	UA_DiagnosticInfo *serviceDiagnostics;
-	UInt16 noOfStringTable;
-	UA_String* stringTable;
+	Int16 noOfStringTable;		// Unsigned: -1 == Empty Array
+	UA_String** stringTable;	//  this is an array of strings, i.e. String** or String* ... []
 	UA_ExtensionObject *additionalHeader;
 }
 UA_AD_ResponseHeader;

+ 50 - 45
tests/check_stack.c

@@ -24,12 +24,11 @@ START_TEST(test_getPacketType_validParameter)
 
 	char buf[] = {'C','L','O'};
 	Int32 pos = 0;
-	AD_RawMessage rawMessage;
-	rawMessage.message = buf;
-	rawMessage.length = 3;
-
-	ck_assert_int_eq(TL_getPacketType(&pos,&rawMessage),packetType_CLO);
+	UA_ByteString msg;
+	msg.Data = buf;
+	msg.Length = 3;
 
+	ck_assert_int_eq(TL_getPacketType(&msg, &pos),packetType_CLO);
 }
 END_TEST
 
@@ -101,7 +100,7 @@ START_TEST(decodeRequestHeader_test_validParameter)
 END_TEST
 */
 
-START_TEST(decodeInt16_test)
+START_TEST(decodeInt16_test_positives)
 {
 	Int32 p = 0;
 	Int16 val;
@@ -111,13 +110,11 @@ START_TEST(decodeInt16_test)
 			0x01,0x00,	// 1
 			0xFF,0x00,	// 255
 			0x00,0x01,	// 256
-			0xFF,0xFF,	// -1
-			0x00,0x80,	// -32768
 	};
 
 	rawMessage.message = mem;
 	rawMessage.length = sizeof(mem);
-	ck_assert_int_eq(rawMessage.length,12);
+	ck_assert_int_eq(rawMessage.length,8);
 
 	decoder_decodeBuiltInDatatype(rawMessage.message,INT16,&p,&val);
 	ck_assert_int_eq(val,0);
@@ -127,12 +124,29 @@ START_TEST(decodeInt16_test)
 	ck_assert_int_eq(val,255);
 	decoder_decodeBuiltInDatatype(rawMessage.message,INT16,&p,&val);
 	ck_assert_int_eq(val,256);
+}
+END_TEST
+START_TEST(decodeInt16_test_negatives)
+{
+	Int32 p = 0;
+	Int16 val;
+	AD_RawMessage rawMessage;
+	char mem[] = {
+			0xFF,0xFF,	// -1
+			0x00,0x80,	// -32768
+	};
+
+	rawMessage.message = mem;
+	rawMessage.length = sizeof(mem);
+	ck_assert_int_eq(rawMessage.length,4);
+
 	decoder_decodeBuiltInDatatype(rawMessage.message,INT16,&p,&val);
 	ck_assert_int_eq(val,-1);
 	decoder_decodeBuiltInDatatype(rawMessage.message,INT16,&p,&val);
 	ck_assert_int_eq(val,-32768);
 }
 END_TEST
+
 START_TEST(encodeInt16_test)
 {
 
@@ -484,61 +498,51 @@ START_TEST(extensionObject_calcSize_test)
 	UA_ExtensionObject extensionObject;
 
 	// empty ExtensionObject
-	extensionObject.TypeId.EncodingByte = NIEVT_TWO_BYTE;; // Numeric TWO BYTES
+	valcalc = extensionObject_calcSize(&the_empty_UA_ExtensionObject);
+	ck_assert_int_eq(valcalc, 1 + 1 + 1);
+
+	// empty ExtensionObject, handcoded
+	extensionObject.TypeId.EncodingByte = NIEVT_TWO_BYTE;
 	extensionObject.TypeId.Identifier.Numeric = 0;
 	extensionObject.Encoding = NO_BODY_IS_ENCODED;
 
 	valcalc = extensionObject_calcSize(&extensionObject);
-	valreal = 3;
-	ck_assert_int_eq(valcalc, valreal);
+	ck_assert_int_eq(valcalc, 1 + 1 + 1);
 
 	// ExtensionObject with ByteString-Body
 	extensionObject.Encoding = BODY_IS_BYTE_STRING;
 	extensionObject.Body.Data = data;
 	extensionObject.Body.Length = 3;
 	valcalc = extensionObject_calcSize(&extensionObject);
-	valreal = 3 + 4 + 3;
-	ck_assert_int_eq(valcalc, valreal);
+	ck_assert_int_eq(valcalc, 3 + 4 + 3);
 
 }
 END_TEST
 
 START_TEST(responseHeader_calcSize_test)
 {
-	Int32 valreal = 1;
-	Int32 valcalc = 0;
-	fail();//ToDo: needs to be adjusted: just to see this needs to be adjusted
-	//ToDo: needs to be adjusted: T_ResponseHeader responseHeader;
+	UA_AD_ResponseHeader responseHeader;
 	UA_DiagnosticInfo diagnosticInfo;
 	UA_ExtensionObject extensionObject;
 
-	//Should have the size of 16 Bytes
-	//ToDo: needs to be adjusted: responseHeader.timestamp = 150014;
-	//ToDo: needs to be adjusted: responseHeader.requestHandle = 514;
-	//ToDo: needs to be adjusted: responseHeader.serviceResult = 504;
-
 	//Should have the size of 26 Bytes
-	diagnosticInfo.EncodingMask = 0x01 | 0x02 | 0x04 | 0x08 | 0x10;
-	diagnosticInfo.SymbolicId = 30;
-	diagnosticInfo.NamespaceUri = 25;
-	diagnosticInfo.LocalizedText = 22;
-	diagnosticInfo.AdditionalInfo.Data = "OPCUA";
-	diagnosticInfo.AdditionalInfo.Length = 5;
-	//ToDo: needs to be adjusted: responseHeader.serviceDiagnostics = &diagnosticInfo;
-	//Should have the size of 4 Bytes
-	//ToDo: needs to be adjusted: responseHeader.noOfStringTable = 0;
-	//Should have the size of 3 Bytes
-	extensionObject.TypeId.EncodingByte = NIEVT_TWO_BYTE;
-	extensionObject.TypeId.Identifier.Numeric = 0;
-	extensionObject.Encoding = 0x00; //binaryBody = false, xmlBody = false
-	//ToDo: needs to be adjusted: responseHeader.additionalHeader = extensionObject;
-
-	//ToDo: needs to be adjusted: valcalc = responseHeader_calcSize(&responseHeader);
-	fail(); //ToDo: needs to be adjusted: Just to see that this needs to be adjusted
-	valreal = 49;
-
-	ck_assert_int_eq(valcalc,valreal);
-
+	diagnosticInfo.EncodingMask = DIEMT_SYMBOLIC_ID | DIEMT_NAMESPACE | DIEMT_LOCALIZED_TEXT | DIEMT_LOCALE | DIEMT_ADDITIONAL_INFO;		// Byte:   1
+	// Indices into to Stringtable of the responseHeader (62541-6 §5.5.12 )
+	diagnosticInfo.SymbolicId = -1;										// Int32:  4
+	diagnosticInfo.NamespaceUri = -1;									// Int32:  4
+	diagnosticInfo.LocalizedText = -1;									// Int32:  4
+	diagnosticInfo.Locale = -1;											// Int32:  4
+	// Additional Info
+	diagnosticInfo.AdditionalInfo.Length = 5;							// Int32:  4
+	diagnosticInfo.AdditionalInfo.Data = "OPCUA";						// Byte[]: 5
+	responseHeader.serviceDiagnostics = &diagnosticInfo;
+	ck_assert_int_eq(diagnosticInfo_calcSize(&diagnosticInfo),1+(4+4+4+4)+(4+5));
+
+	responseHeader.noOfStringTable = -1;								// Int32:	4
+	responseHeader.stringTable = NULL;
+
+	responseHeader.additionalHeader = &the_empty_UA_ExtensionObject;	//		    3
+	ck_assert_int_eq(responseHeader_calcSize(&responseHeader),16+26+4+3);
 }
 END_TEST
 
@@ -684,7 +688,8 @@ Suite *testSuite_decodeInt16(void)
 {
 	Suite *s = suite_create("decodeInt16_test");
 	TCase *tc_core = tcase_create("Core");
-	tcase_add_test(tc_core, decodeInt16_test);
+	tcase_add_test(tc_core, decodeInt16_test_positives);
+	tcase_add_test(tc_core, decodeInt16_test_negatives);
 	suite_add_tcase(s,tc_core);
 	return s;
 }