瀏覽代碼

resurrect testing with binary message from a file

This can be enhanced to test more complex interaction patterns.
Also useful for fuzzing tests.
Julius Pfrommer 9 年之前
父節點
當前提交
57a2d68ad1

+ 11 - 0
src/server/ua_server_binary.c

@@ -480,21 +480,32 @@ void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection
         size_t targetpos = pos - 8 + tcpMessageHeader.messageSize;
         switch(tcpMessageHeader.messageTypeAndFinal & 0xffffff) {
         case UA_MESSAGETYPEANDFINAL_HELF & 0xffffff:
+            UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_NETWORK,
+                         "Process a HEL on Connection %i", connection->sockfd);
             processHEL(connection, msg, &pos);
             break;
         case UA_MESSAGETYPEANDFINAL_OPNF & 0xffffff:
+            UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_NETWORK,
+                         "Process a OPN on Connection %i", connection->sockfd);
             processOPN(connection, server, msg, &pos);
             break;
         case UA_MESSAGETYPEANDFINAL_MSGF & 0xffffff:
 #ifndef UA_ENABLE_NONSTANDARD_STATELESS
             if(connection->state != UA_CONNECTION_ESTABLISHED) {
+                UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_NETWORK,
+                             "Received a MSG where the connection is not established on Connection %i",
+                             connection->sockfd);
                 connection->close(connection);
                 return;
             }
 #endif
+            UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_NETWORK,
+                         "Process a MSG on Connection %i", connection->sockfd);
             processMSG(connection, server, msg, &pos);
             break;
         case UA_MESSAGETYPEANDFINAL_CLOF & 0xffffff:
+            UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_NETWORK,
+                         "Process a CLO on Connection %i", connection->sockfd);
             processCLO(connection, server, msg, &pos);
             connection->close(connection);
             return;

+ 13 - 13
tests/CMakeLists.txt

@@ -62,21 +62,21 @@ add_test(session ${CMAKE_CURRENT_BINARY_DIR}/check_session)
 
 # test with canned interactions from files
 
-#add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/client_HELOPN.bin
-#                   PRE_BUILD
-#                   COMMAND python ${PROJECT_SOURCE_DIR}/tools/hex2bin.py ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_HELOPN.hex
-#                                  ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_CreateActivateSession.hex
-#                   DEPENDS ${PROJECT_SOURCE_DIR}/tools/hex2bin.py
-#                           ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_HELOPN.hex)
-
-#set(check_fileinput_source check_server_interaction_fileinput.c testing_networklayers.c $<TARGET_OBJECTS:open62541-object>)
-#if(NOT UA_ENABLE_AMALGAMATION)
-#    list(APPEND check_fileinput_source ${PROJECT_SOURCE_DIR}/examples/logger_stdout.c)
-#endif()
-#add_executable(check_server_interaction_fileinput ${check_fileinput_source})
+add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/client_HELOPN.bin
+                  PRE_BUILD
+                  COMMAND python ${PROJECT_SOURCE_DIR}/tools/hex2bin.py ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_HELOPN.hex
+                                 ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_CreateActivateSession.hex
+                  DEPENDS ${PROJECT_SOURCE_DIR}/tools/hex2bin.py
+                          ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_HELOPN.hex)
+
+add_executable(check_server_binary_messages check_server_binary_messages.c testing_networklayers.c $<TARGET_OBJECTS:open62541-object>)
+target_include_directories(check_server_binary_messages PRIVATE ${PROJECT_SOURCE_DIR}/src/server)
+target_link_libraries(check_server_binary_messages ${LIBS})
+add_test(NAME check_server_binary_messages_helopn
+         COMMAND check_server_binary_messages client_HELOPN.bin
+         ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/client_HELOPN.bin)
 
 #target_include_directories(check_server_interaction_fileinput PRIVATE ${PROJECT_SOURCE_DIR}/examples)
 #target_include_directories(check_server_interaction_fileinput PRIVATE ${PROJECT_BINARY_DIR})
 #target_link_libraries(check_server_interaction_fileinput ${LIBS})
 #add_test(server_interaction_fileinput ${CMAKE_CURRENT_BINARY_DIR}/check_server_interaction_fileinput ${CMAKE_CURRENT_BINARY_DIR}/client_HELOPN.bin)
-#add_custom_target(server_interaction_fileinput ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/client_HELOPN.bin)

+ 69 - 0
tests/check_server_binary_messages.c

@@ -0,0 +1,69 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include "check.h"
+
+#include "ua_server.h"
+#include "ua_server_internal.h"
+#include "logger_stdout.h"
+#include "testing_networklayers.h"
+
+size_t files;
+char **filenames;
+
+static UA_ByteString readFile(char *filename) {
+    UA_ByteString buf = UA_BYTESTRING_NULL;
+    size_t length;
+    FILE *f = fopen(filename,"r");
+
+    if(f) {
+        fseek(f, 0, SEEK_END);
+        length = ftell(f);
+        rewind(f);
+        buf.data = malloc(length);
+        fread(buf.data, sizeof(char), length, f);
+        buf.length = length;
+        fclose(f);
+    }
+
+    return buf;
+}
+
+START_TEST(processMessage) {
+    UA_Connection c = createDummyConnection();
+    UA_ServerConfig config = UA_ServerConfig_standard;
+    config.logger = Logger_Stdout;
+    UA_Server *server = UA_Server_new(config);
+    for(size_t i = 0; i < files; i++) {
+        UA_ByteString msg = readFile(filenames[i]);
+        UA_Server_processBinaryMessage(server, &c, &msg);
+        UA_ByteString_deleteMembers(&msg);
+    }
+	UA_Server_delete(server);
+    UA_Connection_deleteMembers(&c);
+}
+END_TEST
+
+static Suite *testSuite_binaryMessages(void) {
+	Suite *s = suite_create("Test server with messages stored in text files");
+	TCase *tc_messages = tcase_create("binary messages");
+	tcase_add_test(tc_messages, processMessage);
+	suite_add_tcase(s, tc_messages);
+	return s;
+}
+
+int main(int argc, char **argv) {
+    if(argc < 2)
+        return EXIT_FAILURE;
+    filenames = &argv[1];
+    files = argc - 1;
+	int number_failed = 0;
+	Suite *s;
+	SRunner *sr;
+	s  = testSuite_binaryMessages();
+	sr = srunner_create(s);
+	srunner_set_fork_status(sr, CK_NOFORK);
+	srunner_run_all(sr, CK_NORMAL);
+	number_failed += srunner_ntests_failed(sr);
+	srunner_free(sr);
+	return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}

+ 0 - 65
tests/check_server_interaction_fileinput.c

@@ -1,65 +0,0 @@
-#include <stdlib.h>
-#include "check.h"
-#ifdef NOT_AMALGATED
-    #include "ua_server.h"
-#else
-    #include "open62541.h"
-#endif
-#include "testing_networklayers.h"
-#include "logger_stdout.h"
-
-#include <stdio.h>
-
-UA_Boolean running = 1;
-UA_UInt32 read_count = 0;
-UA_UInt32 max_reads;
-char **filenames;
-
-static UA_StatusCode writeCallback(void *handle, UA_ByteString *buf) {
-    return UA_STATUSCODE_GOOD;
-}
-
-static void readCallback(void) {
-    read_count++;
-    if(read_count > max_reads)
-        running = UA_FALSE;
-}
-
-START_TEST(readVariable) {
-	UA_Server *server = UA_Server_new(UA_ServerConfig_standard);
-    UA_Server_setLogger(server, Logger_Stdout_new());
-    UA_Server_addNetworkLayer(server, ServerNetworkLayerFileInput_new(max_reads, filenames, readCallback,
-                                                                      writeCallback, NULL));
-    UA_StatusCode retval = UA_Server_run(server, 1, &running);
-	UA_Server_delete(server);
-
-	ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
-}
-END_TEST
-
-static Suite *testSuite_builtin(void) {
-	Suite *s = suite_create("Test server with client messages stored in text files");
-
-	TCase *tc_nano = tcase_create("nano profile");
-	tcase_add_test(tc_nano, readVariable);
-	suite_add_tcase(s, tc_nano);
-
-	return s;
-}
-
-int main(int argc, char **argv) {
-    if(argc < 2)
-        return EXIT_FAILURE;
-    filenames = &argv[1];
-    max_reads = argc - 1;
-	int      number_failed = 0;
-	Suite   *s;
-	SRunner *sr;
-	s  = testSuite_builtin();
-	sr = srunner_create(s);
-	srunner_set_fork_status(sr, CK_NOFORK);
-	srunner_run_all(sr, CK_NORMAL);
-	number_failed += srunner_ntests_failed(sr);
-	srunner_free(sr);
-	return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
-}

+ 31 - 103
tests/testing_networklayers.c

@@ -1,114 +1,42 @@
-#include <unistd.h>
-#include <fcntl.h>
-#include <malloc.h>
-#include <assert.h>
+#include <stdlib.h>
 #include "testing_networklayers.h"
 
-typedef struct NetworkLayer_FileInput {
-	UA_Connection connection;
-    UA_UInt32 files;
-    char **filenames;
-    UA_UInt32 files_read;
-    UA_StatusCode (*writeCallback)(struct NetworkLayer_FileInput *handle, const UA_ByteString *buf);
-    void (*readCallback)(void);
-    void *callbackHandle;
-} NetworkLayer_FileInput;
-
-/** Accesses only the sockfd in the handle. Can be run from parallel threads. */
-static UA_StatusCode writeCallback(NetworkLayer_FileInput *handle, const UA_ByteString *buf) {
-    handle->writeCallback(handle->callbackHandle, buf);
+static UA_StatusCode
+dummyGetSendBuffer(UA_Connection *connection, size_t length, UA_ByteString *buf) {
+    buf->data = malloc(length);
+    buf->length = length;
     return UA_STATUSCODE_GOOD;
 }
 
-static void closeCallback(NetworkLayer_FileInput *handle) {
-}
-
-static UA_StatusCode NetworkLayer_FileInput_start(NetworkLayer_FileInput *layer, UA_Logger *logger) {
-    return UA_STATUSCODE_GOOD;
-}
-
-static UA_Int32
-NetworkLayer_FileInput_getWork(NetworkLayer_FileInput *layer, UA_WorkItem **workItems, UA_UInt16 timeout)
-{
-    layer->readCallback();
-
-    // open a new connection
-    // return a single buffer with the entire file
-
-    if(layer->files >= layer->files_read)
-        return 0;
-    
-    int filefd = open(layer->filenames[layer->files_read], O_RDONLY);
-    layer->files_read++;
-    if(filefd == -1)
-        return 0;
-
-    UA_Byte *buf = malloc(layer->connection.localConf.maxMessageSize);
-    UA_Int32 bytes_read = read(filefd, buf, layer->connection.localConf.maxMessageSize);
-    close(filefd);
-    if(bytes_read <= 0) {
-        free(buf);
-        return 0;
-    }
-        
-    *workItems = malloc(sizeof(UA_WorkItem));
-    UA_WorkItem *work = *workItems;
-    work->type = UA_WORKITEMTYPE_BINARYMESSAGE;
-    work->work.binaryMessage.connection = &layer->connection;
-    work->work.binaryMessage.message = (UA_ByteString){.length = bytes_read, .data = (UA_Byte*)buf};
-    return 1;
-}
-
-static UA_Int32 NetworkLayer_FileInput_stop(NetworkLayer_FileInput * layer, UA_WorkItem **workItems) {
-    // remove the connection in the server
-    // return removeAllConnections(layer, workItems);
-    return 0;
+static void
+releaseSendBuffer(UA_Connection *connection, UA_ByteString *buf) {
+    free(buf->data);
 }
 
-static void NetworkLayer_FileInput_delete(NetworkLayer_FileInput *layer) {
-	free(layer);
-}
-
-static UA_StatusCode NetworkLayer_FileInput_getBuffer(UA_Connection *connection, UA_ByteString *buf, size_t minSize) {
-    buf->data = malloc(minSize);
-    if(!buf->data)
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    buf->length = minSize;
-    return UA_STATUSCODE_GOOD;
-}
-
-static void NetworkLayer_FileInput_releaseBuffer(UA_Connection *connection, UA_ByteString *buf) {
+static UA_StatusCode
+dummySend(UA_Connection *connection, UA_ByteString *buf) {
     UA_ByteString_deleteMembers(buf);
+    return UA_STATUSCODE_GOOD;
 }
 
-UA_ServerNetworkLayer
-ServerNetworkLayerFileInput_new(UA_UInt32 files, char **filenames, void(*readCallback)(void),
-                                UA_StatusCode (*writeCallback) (void*, UA_ByteString *buf),
-                                void *callbackHandle)
-{
-    NetworkLayer_FileInput *layer = malloc(sizeof(NetworkLayer_FileInput));
-    layer->connection.state = UA_CONNECTION_OPENING;
-    layer->connection.localConf = UA_ConnectionConfig_standard;
-    layer->connection.channel = (void*)0;
-    layer->connection.close = (void (*)(UA_Connection*))closeCallback;
-    layer->connection.write = (UA_StatusCode (*)(UA_Connection*, const UA_ByteString*))writeCallback;
-    layer->connection.releaseBuffer = NetworkLayer_FileInput_releaseBuffer;
-    layer->connection.getBuffer = NetworkLayer_FileInput_getBuffer;
-
-    layer->files = files;
-    layer->filenames = filenames;
-    layer->files_read = 0;
-    layer->readCallback = readCallback;
-    layer->writeCallback = (UA_StatusCode(*)(struct NetworkLayer_FileInput *handle, const UA_ByteString *buf)) writeCallback;
-    layer->callbackHandle = callbackHandle;
-    
-    UA_ServerNetworkLayer nl;
-    nl.nlHandle = layer;
-    nl.start = (UA_StatusCode (*)(void*, UA_Logger *logger))NetworkLayer_FileInput_start;
-    nl.getWork = (UA_Int32 (*)(void*, UA_WorkItem**, UA_UInt16)) NetworkLayer_FileInput_getWork;
-    nl.stop = (UA_Int32 (*)(void*, UA_WorkItem**)) NetworkLayer_FileInput_stop;
-    nl.free = (void (*)(void*))NetworkLayer_FileInput_delete;
-    nl.discoveryUrl = UA_String_new();
-    *nl.discoveryUrl = UA_STRING_ALLOC("");
-    return nl;
+static void
+dummyClose(UA_Connection *connection) {
+    return;
+}
+
+UA_Connection createDummyConnection(void) {
+    UA_Connection c;
+    c.state = UA_CONNECTION_ESTABLISHED;
+    c.localConf = UA_ConnectionConfig_standard;
+    c.remoteConf = UA_ConnectionConfig_standard;
+    c.channel = NULL;
+    c.sockfd = 0;
+    c.handle = NULL;
+    c.incompleteMessage = UA_BYTESTRING_NULL;
+    c.getSendBuffer = dummyGetSendBuffer;
+    c.send = dummySend;
+    c.recv = NULL;
+    c.releaseRecvBuffer = NULL;
+    c.close = dummyClose;
+    return c;
 }

+ 2 - 9
tests/testing_networklayers.h

@@ -1,16 +1,9 @@
 #ifndef TESTING_NETWORKLAYERS_H_
 #define TESTING_NETWORKLAYERS_H_
 
-#ifdef NOT_AMALGATED
-# include "ua_server.h"
-#else
-# include "open62541.h"
-#endif
+#include "ua_server.h"
 
 /** @brief Create the TCP networklayer and listen to the specified port */
-UA_ServerNetworkLayer
-ServerNetworkLayerFileInput_new(UA_UInt32 files, char **filenames, void(*readCallback)(void),
-                                UA_StatusCode (*writeCallback) (void*, UA_ByteString *buf),
-                                void *callbackHandle);
+UA_Connection createDummyConnection(void);
 
 #endif /* TESTING_NETWORKLAYERS_H_ */