Просмотр исходного кода

Python improvements

Use StringIO and fix python3 build
Stefan Profanter лет назад: 7
Родитель
Сommit
a4d0ea98ab

+ 13 - 2
.travis.yml

@@ -18,7 +18,9 @@ matrix:
   include:
     - os: linux
       compiler: gcc
-      env: ANALYZE=false
+      env:
+        - ANALYZE=false
+        - PYTHON=python2
     - os: linux
       compiler: gcc
       env: ANALYZE=true
@@ -29,7 +31,14 @@ matrix:
         - docker
     - os: linux
       compiler: clang
-      env: ANALYZE=false
+      env:
+        - ANALYZE=false
+        - PYTHON=python2
+    - os: linux
+      compiler: clang
+      env:
+        - ANALYZE=false
+        - PYTHON=python3
     - os: linux
       compiler: clang
       env: ANALYZE=true
@@ -62,6 +71,8 @@ addons:
       - libsubunit-dev
       - libx11-dev
       - mingw-w64
+      - python-six
+      - python3-six
       - texlive-fonts-recommended
       - texlive-latex-extra
       - texlive-latex-recommended

+ 2 - 1
Dockerfile

@@ -1,7 +1,8 @@
 FROM alpine:3.5
-RUN apk add --no-cache cmake gcc g++ musl-dev python make && rm -rf /var/cache/apk/*
+RUN apk add --no-cache cmake gcc g++ musl-dev python py-pip make && rm -rf /var/cache/apk/*
 ADD . /tmp/open62541
 WORKDIR /tmp/open62541/build
+RUN pip install six
 RUN cmake -DUA_ENABLE_AMALGAMATION=true  \
           -DBUILD_SHARED_LIBS=true \
           /tmp/open62541 

+ 133 - 128
tests/CMakeLists.txt

@@ -201,131 +201,136 @@ add_test_valgrind(check_client_highlevel ${TESTS_BINARY_DIR}/check_client_highle
 #                           #
 #############################
 
-# Generate types for DI namespace
-set(UA_TYPES_OUT "ua_types_di")
-add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated.c
-                   ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated.h
-                   ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated_handling.h
-                   ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated_encoding_binary.h
-                   PRE_BUILD
-                   COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
-                   --namespace=2
-                   --type-csv=${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/OpcUaDiModel.csv
-                   --type-bsd=${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd
-                   --no-builtin
-                   ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}
-                   DEPENDS ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
-                   ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/OpcUaDiModel.csv
-                   ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd)
-
-# Generate types for ADI namespace
-set(UA_TYPES_OUT "ua_types_adi")
-add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated.c
-                   ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated.h
-                   ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated_handling.h
-                   ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated_encoding_binary.h
-                   PRE_BUILD
-                   COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
-                   --namespace=3
-                   --type-csv=${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/OpcUaAdiModel.csv
-                   --type-bsd=${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/Opc.Ua.Adi.Types.bsd
-                   --no-builtin
-                   ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}
-                   DEPENDS ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
-                   ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/OpcUaAdiModel.csv
-                   ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/Opc.Ua.Adi.Types.bsd)
-
-# generate DI namespace
-add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_di.c
-                   ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_di.h
-                   PRE_BUILD
-                   COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset_compiler.py
-                   --internal-headers
-                   --types-array=UA_TYPES
-                   --types-array=UA_TYPES_DI
-                   --existing ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml
-                   --xml ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml
-                   ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_di
-                   DEPENDS ${UA_NAMESPACE0_XML}
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset_compiler.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodes.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/datatypes.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541_nodes.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541_datatypes.py
-                   ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml
-                   ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml
-                   )
-
-
-# generate ADI namespace which is using DI
-add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_adi.c
-                   ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_adi.h
-                   PRE_BUILD
-                   COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset_compiler.py
-                   --internal-headers
-                   --types-array=UA_TYPES
-                   --types-array=UA_TYPES_DI
-                   --types-array=UA_TYPES_ADI
-                   --existing ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml
-                   --existing ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml
-                   --xml ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/Opc.Ua.Adi.NodeSet2.xml
-                   ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_adi
-                   DEPENDS ${UA_NAMESPACE0_XML}
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset_compiler.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodes.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/datatypes.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541_nodes.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541_datatypes.py
-                   ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml
-                   ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml
-                   ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/Opc.Ua.Adi.NodeSet2.xml
-                   )
-
-# generate PLCopen namespace which is using DI
-add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_plc.c
-                   ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_plc.h
-                   PRE_BUILD
-                   COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset_compiler.py
-                   --internal-headers
-                   --types-array=UA_TYPES
-                   --types-array=UA_TYPES_DI
-                   # PLCopen has no specific type definition, thus use the default UA_TYPES to ignore it
-                   --types-array=UA_TYPES
-                   --existing ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml
-                   --existing ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml
-                   --xml ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/PLCopen/Opc.Ua.Plc.NodeSet2.xml
-                   ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_plc
-                   DEPENDS ${UA_NAMESPACE0_XML}
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset_compiler.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodes.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/datatypes.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541_nodes.py
-                   ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541_datatypes.py
-                   ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml
-                   ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/PLCopen/Opc.Ua.Plc.NodeSet2.xml
-                   )
-
-add_executable(check_nodeset_compiler_adi
-               check_nodeset_compiler_adi.c
-               ${PROJECT_BINARY_DIR}/src_generated/ua_types_di_generated.c
-               ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_di.c
-               ${PROJECT_BINARY_DIR}/src_generated/ua_types_adi_generated.c
-               ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_adi.c
-               $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
-target_link_libraries(check_nodeset_compiler_adi ${LIBS})
-add_test_valgrind(check_nodeset_compiler_adi ${TESTS_BINARY_DIR}/check_nodeset_compiler_adi)
-
-add_executable(check_nodeset_compiler_plc
-               check_nodeset_compiler_plc.c
-               ${PROJECT_BINARY_DIR}/src_generated/ua_types_di_generated.c
-               ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_di.c
-               ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_plc.c
-               $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
-target_link_libraries(check_nodeset_compiler_plc ${LIBS})
-add_test_valgrind(check_nodeset_compiler_plc ${TESTS_BINARY_DIR}/check_nodeset_compiler_plc)
+# can only be tested if UA_ENABLE_FULL_NS0
+
+if (UA_ENABLE_FULL_NS0)
+
+    # Generate types for DI namespace
+    set(UA_TYPES_OUT "ua_types_di")
+    add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated.c
+                       ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated.h
+                       ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated_handling.h
+                       ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated_encoding_binary.h
+                       PRE_BUILD
+                       COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
+                       --namespace=2
+                       --type-csv=${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/OpcUaDiModel.csv
+                       --type-bsd=${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd
+                       --no-builtin
+                       ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}
+                       DEPENDS ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
+                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/OpcUaDiModel.csv
+                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd)
+
+    # Generate types for ADI namespace
+    set(UA_TYPES_OUT "ua_types_adi")
+    add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated.c
+                       ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated.h
+                       ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated_handling.h
+                       ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated_encoding_binary.h
+                       PRE_BUILD
+                       COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
+                       --namespace=3
+                       --type-csv=${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/OpcUaAdiModel.csv
+                       --type-bsd=${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/Opc.Ua.Adi.Types.bsd
+                       --no-builtin
+                       ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}
+                       DEPENDS ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
+                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/OpcUaAdiModel.csv
+                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/Opc.Ua.Adi.Types.bsd)
+
+    # generate DI namespace
+    add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_di.c
+                       ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_di.h
+                       PRE_BUILD
+                       COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset_compiler.py
+                       --internal-headers
+                       --types-array=UA_TYPES
+                       --types-array=UA_TYPES_DI
+                       --existing ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml
+                       --xml ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml
+                       ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_di
+                       DEPENDS ${UA_NAMESPACE0_XML}
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset_compiler.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodes.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/datatypes.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541_nodes.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541_datatypes.py
+                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml
+                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml
+                       )
+
+
+    # generate ADI namespace which is using DI
+    add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_adi.c
+                       ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_adi.h
+                       PRE_BUILD
+                       COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset_compiler.py
+                       --internal-headers
+                       --types-array=UA_TYPES
+                       --types-array=UA_TYPES_DI
+                       --types-array=UA_TYPES_ADI
+                       --existing ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml
+                       --existing ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml
+                       --xml ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/Opc.Ua.Adi.NodeSet2.xml
+                       ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_adi
+                       DEPENDS ${UA_NAMESPACE0_XML}
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset_compiler.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodes.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/datatypes.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541_nodes.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541_datatypes.py
+                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml
+                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml
+                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/Opc.Ua.Adi.NodeSet2.xml
+                       )
+
+    # generate PLCopen namespace which is using DI
+    add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_plc.c
+                       ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_plc.h
+                       PRE_BUILD
+                       COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset_compiler.py
+                       --internal-headers
+                       --types-array=UA_TYPES
+                       --types-array=UA_TYPES_DI
+                       # PLCopen has no specific type definition, thus use the default UA_TYPES to ignore it
+                       --types-array=UA_TYPES
+                       --existing ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml
+                       --existing ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml
+                       --xml ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/PLCopen/Opc.Ua.Plc.NodeSet2.xml
+                       ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_plc
+                       DEPENDS ${UA_NAMESPACE0_XML}
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset_compiler.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodes.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/nodeset.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/datatypes.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541_nodes.py
+                       ${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/backend_open62541_datatypes.py
+                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml
+                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/PLCopen/Opc.Ua.Plc.NodeSet2.xml
+                       )
+
+    add_executable(check_nodeset_compiler_adi
+                   check_nodeset_compiler_adi.c
+                   ${PROJECT_BINARY_DIR}/src_generated/ua_types_di_generated.c
+                   ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_di.c
+                   ${PROJECT_BINARY_DIR}/src_generated/ua_types_adi_generated.c
+                   ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_adi.c
+                   $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
+    target_link_libraries(check_nodeset_compiler_adi ${LIBS})
+    add_test_valgrind(check_nodeset_compiler_adi ${TESTS_BINARY_DIR}/check_nodeset_compiler_adi)
+
+    add_executable(check_nodeset_compiler_plc
+                   check_nodeset_compiler_plc.c
+                   ${PROJECT_BINARY_DIR}/src_generated/ua_types_di_generated.c
+                   ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_di.c
+                   ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_plc.c
+                   $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
+    target_link_libraries(check_nodeset_compiler_plc ${LIBS})
+    add_test_valgrind(check_nodeset_compiler_plc ${TESTS_BINARY_DIR}/check_nodeset_compiler_plc)
+endif()

+ 14 - 0
tests/check_types_memory.c

@@ -14,6 +14,20 @@
 #include "ua_util.h"
 #include "check.h"
 
+// Define types to a dummy value if they are not available (e.g. not built with NS0 full)
+#ifndef UA_TYPES_UNION
+#define UA_TYPES_UNION UA_TYPES_COUNT
+#endif
+#ifndef UA_TYPES_HISTORYREADDETAILS
+#define UA_TYPES_HISTORYREADDETAILS UA_TYPES_COUNT
+#endif
+#ifndef UA_TYPES_NOTIFICATIONDATA
+#define UA_TYPES_NOTIFICATIONDATA UA_TYPES_COUNT
+#endif
+#ifndef UA_TYPES_MONITORINGFILTERRESULT
+#define UA_TYPES_MONITORINGFILTERRESULT UA_TYPES_COUNT
+#endif
+
 START_TEST(newAndEmptyObjectShallBeDeleted) {
     // given
     void *obj = UA_new(&UA_TYPES[_i]);

+ 14 - 4
tools/nodeset_compiler/backend_open62541.py

@@ -23,6 +23,10 @@ import string
 from collections import deque
 from os.path import basename
 import logging
+try:
+    from StringIO import StringIO
+except ImportError:
+    from io import StringIO
 
 logger = logging.getLogger(__name__)
 
@@ -159,13 +163,13 @@ def generateOpen62541Code(nodeset, outfilename, supressGenerationOfAttribute=[],
     outfilebase = basename(outfilename)
     # Printing functions
     outfileh = open(outfilename + ".h", r"w+")
-    outfilec = open(outfilename + ".c", r"w+")
+    outfilec = StringIO()
 
     def writeh(line):
-        print(unicode(line).encode('utf8'), end='\n', file=outfileh)
+        print(unicode(line), end='\n', file=outfileh)
 
     def writec(line):
-        print(unicode(line).encode('utf8'), end='\n', file=outfilec)
+        print(unicode(line), end='\n', file=outfilec)
 
     additionalHeaders = ""
     if len(typesArray) > 0:
@@ -212,7 +216,7 @@ UA_StatusCode retVal = UA_STATUSCODE_GOOD;
 """ % (outfilebase, outfilebase))
 
     parentrefs = getSubTypesOf(nodeset, nodeset.getNodeByBrowseName("HierarchicalReferences"))
-    parentrefs = map(lambda x: x.id, parentrefs)
+    parentrefs = list(map(lambda x: x.id, parentrefs))
 
     # Generate namespaces (don't worry about duplicates)
     writec("/* Use namespace ids generated by the server */")
@@ -243,5 +247,11 @@ UA_StatusCode retVal = UA_STATUSCODE_GOOD;
     # Finalize the generated source
     writec("return retVal;")
     writec("} // closing nodeset()")
+
     outfileh.close()
+    fullCode = outfilec.getvalue()
+    outfilec.close()
+
+    outfilec = open(outfilename + ".c", r"w+")
+    outfilec.write(fullCode)
     outfilec.close()

+ 2 - 1
tools/nodeset_compiler/backend_open62541_datatypes.py

@@ -79,7 +79,8 @@ def generateNodeValueCode(node, instanceName, asIndirect=False, max_string_lengt
     elif type(node) == XmlElement:
         return generateXmlElementCode(node.value, asIndirect, max_string_length)
     elif type(node) == ByteString:
-        return generateByteStringCode(re.sub(r"[\r\n]+", "", node.value), asIndirect, max_string_length)
+        # replace whitespaces between tags and remove newlines
+        return generateByteStringCode(re.sub(r">\s*<", "><", re.sub(r"[\r\n]+", "", node.value)), asIndirect, max_string_length)
     elif type(node) == LocalizedText:
         return generateLocalizedTextCode(node, asIndirect, max_string_length)
     elif type(node) == NodeId:

+ 6 - 4
tools/nodeset_compiler/datatypes.py

@@ -26,6 +26,8 @@ import xml.dom.minidom as dom
 from constants import *
 from base64 import *
 
+import six
+
 if sys.version_info[0] >= 3:
     # strings are already parsed to unicode
     def unicode(s):
@@ -178,7 +180,7 @@ class Value(object):
         if len(enc) == 1:
             # 0: ['BuiltinType']          either builtin type
             # 1: [ [ 'Alias', [...], n] ] or single alias for possible multipart
-            if isinstance(enc[0], basestring):
+            if isinstance(enc[0], six.string_types):
                 # 0: 'BuiltinType'
                 if alias != None:
                     if not xmlvalue.localName == alias:
@@ -200,7 +202,7 @@ class Value(object):
                 # 1: ['Alias', [...], n]
                 # Let the next elif handle this
                 return self.__parseXMLSingleValue(xmlvalue, parentDataTypeNode, alias=alias, encodingPart=enc[0])
-        elif len(enc) == 3 and isinstance(enc[0], basestring):
+        elif len(enc) == 3 and isinstance(enc[0], six.string_types):
             # [ 'Alias', [...], 0 ]          aliased multipart
             if alias == None:
                 alias = enc[0]
@@ -432,7 +434,7 @@ class String(Value):
         if xmlvalue.firstChild == None:
             self.value = ""  # Catch XML <String /> by setting the value to a default
         else:
-            self.value = str(unicode(xmlvalue.firstChild.data))
+            self.value = unicode(xmlvalue.firstChild.data)
 
 class XmlElement(String):
     def __init__(self, xmlelement=None):
@@ -453,7 +455,7 @@ class ByteString(Value):
         if xmlvalue.firstChild == None:
             self.value = []  # Catch XML <ByteString /> by setting the value to a default
         else:
-            self.value = b64decode(xmlvalue.firstChild.data)
+            self.value = b64decode(xmlvalue.firstChild.data).decode("utf-8")
 
 class ExtensionObject(Value):
     def __init__(self, xmlelement=None):

+ 2 - 3
tools/nodeset_compiler/nodes.py

@@ -18,7 +18,6 @@
 
 import sys
 import logging
-from sets import Set
 from datatypes import *
 from constants import *
 
@@ -67,8 +66,8 @@ class Node(object):
         self.symbolicName = String()
         self.writeMask = 0
         self.userWriteMask = 0
-        self.references = Set()
-        self.inverseReferences = Set()
+        self.references = set()
+        self.inverseReferences = set()
         self.hidden = False
 
     def __str__(self):

+ 10 - 3
tools/nodeset_compiler/nodeset.py

@@ -27,6 +27,7 @@ logger = logging.getLogger(__name__)
 
 from nodes import *
 from opaque_type_mapping import opaque_type_mapping
+import codecs
 
 ####################
 # Helper Functions #
@@ -201,7 +202,13 @@ class NodeSet(object):
 
     def addNodeSet(self, xmlfile, hidden=False, typesArray="UA_TYPES"):
         # Extract NodeSet DOM
-        nodesets = dom.parse(xmlfile).getElementsByTagName("UANodeSet")
+
+        fileContent = xmlfile.read()
+        # Remove BOM since the dom parser cannot handle it on python 3 windows
+        if fileContent.startswith( codecs.BOM_UTF8 ):
+            fileContent = fileContent.lstrip( codecs.BOM_UTF8 )
+
+        nodesets = dom.parseString(fileContent).getElementsByTagName("UANodeSet")
         if len(nodesets) == 0 or len(nodesets) > 1:
             raise Exception(self, self.originXML + " contains no or more then 1 nodeset")
         nodeset = nodesets[0]
@@ -296,7 +303,7 @@ class NodeSet(object):
         return node
                 
     def getDataTypeNode(self, dataType):
-        if isinstance(dataType, basestring):
+        if isinstance(dataType, six.string_types):
             if not valueIsInternalType(dataType):
                 logger.error("Not a valid dataType string: " + dataType)
                 return None
@@ -321,4 +328,4 @@ class NodeSet(object):
                                         self.getNodeByBrowseName("HasEncoding"),
                                         [])
         relevant_types = map(lambda x: x.id, relevant_types)
-        return relevant_types
+        return list(relevant_types)

+ 2 - 2
tools/nodeset_compiler/nodeset_compiler.py

@@ -30,7 +30,7 @@ from backend_open62541 import generateOpen62541Code
 parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter)
 parser.add_argument('-e', '--existing',
                     metavar="<existingNodeSetXML>",
-                    type=argparse.FileType('r'),
+                    type=argparse.FileType('rb'),
                     dest="existing",
                     action='append',
                     default=[],
@@ -38,7 +38,7 @@ parser.add_argument('-e', '--existing',
 
 parser.add_argument('-x', '--xml',
                     metavar="<nodeSetXML>",
-                    type=argparse.FileType('r'),
+                    type=argparse.FileType('rb'),
                     action='append',
                     dest="infiles",
                     default=[],

+ 18 - 17
tools/travis/travis_linux_script.sh

@@ -72,7 +72,7 @@ else
     echo -e "\r\n== Documentation and certificate build =="  && echo -en 'travis_fold:start:script.build.doc\\r'
     mkdir -p build
     cd build
-    cmake -DCMAKE_BUILD_TYPE=Release -DUA_BUILD_EXAMPLES=ON -DUA_BUILD_SELFSIGNED_CERTIFICATE=ON ..
+    cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/$PYTHON -DCMAKE_BUILD_TYPE=Release -DUA_BUILD_EXAMPLES=ON -DUA_BUILD_SELFSIGNED_CERTIFICATE=ON ..
     make doc
     make doc_pdf
     make selfsigned
@@ -85,7 +85,7 @@ else
     echo -e "\r\n== Full Namespace 0 Generation ==" && echo -en 'travis_fold:start:script.build.ns0\\r'
     mkdir -p build
     cd build
-    cmake -DCMAKE_BUILD_TYPE=Debug -DUA_ENABLE_FULL_NS0=ON -DUA_BUILD_EXAMPLES=ON  ..
+    cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/$PYTHON -DCMAKE_BUILD_TYPE=Debug -DUA_ENABLE_FULL_NS0=ON -DUA_BUILD_EXAMPLES=ON  ..
     make -j
     if [ $? -ne 0 ] ; then exit 1 ; fi
     cd .. && rm build -rf
@@ -137,7 +137,7 @@ else
 
     echo -e "\r\n== Compile release build for 64-bit linux =="  && echo -en 'travis_fold:start:script.build.linux_64\\r'
     mkdir -p build && cd build
-    cmake -DCMAKE_BUILD_TYPE=Release -DUA_ENABLE_AMALGAMATION=ON -DUA_BUILD_EXAMPLES=ON ..
+    cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/$PYTHON -DCMAKE_BUILD_TYPE=Release -DUA_ENABLE_AMALGAMATION=ON -DUA_BUILD_EXAMPLES=ON ..
     make -j
     if [ $? -ne 0 ] ; then exit 1 ; fi
     tar -pczf open62541-linux64.tar.gz ../../doc_latex/open62541.pdf ../LICENSE ../AUTHORS ../README.md ./bin/examples/server ./bin/examples/client ./bin/libopen62541.a open62541.h open62541.c
@@ -158,13 +158,13 @@ else
 
     echo "Compile as shared lib version" && echo -en 'travis_fold:start:script.build.shared_libs\\r'
     mkdir -p build && cd build
-    cmake -DBUILD_SHARED_LIBS=ON -DUA_ENABLE_AMALGAMATION=ON -DUA_BUILD_EXAMPLES=ON ..
+    cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/$PYTHON -DBUILD_SHARED_LIBS=ON -DUA_ENABLE_AMALGAMATION=ON -DUA_BUILD_EXAMPLES=ON ..
     make -j
     if [ $? -ne 0 ] ; then exit 1 ; fi
     cd .. && rm build -rf
     echo -en 'travis_fold:end:script.build.shared_libs\\r'echo -e "\r\n==Compile multithreaded version==" && echo -en 'travis_fold:start:script.build.multithread\\r'
     mkdir -p build && cd build
-    cmake -DUA_ENABLE_MULTITHREADING=ON -DUA_BUILD_EXAMPLES=ON ..
+    cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/$PYTHON -DUA_ENABLE_MULTITHREADING=ON -DUA_BUILD_EXAMPLES=ON ..
     make -j
     if [ $? -ne 0 ] ; then exit 1 ; fi
     cd .. && rm build -rf
@@ -172,14 +172,14 @@ else
 
     echo -e "\r\n== Compile without discovery version ==" && echo -en 'travis_fold:start:script.build.unit_test_valgrind\\r'
     mkdir -p build && cd build
-    cmake -DUA_ENABLE_DISCOVERY=OFF -DUA_ENABLE_DISCOVERY_MULTICAST=OFF -DUA_BUILD_EXAMPLES=ON ..
+    cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/$PYTHON -DUA_ENABLE_DISCOVERY=OFF -DUA_ENABLE_DISCOVERY_MULTICAST=OFF -DUA_BUILD_EXAMPLES=ON ..
     make -j
     if [ $? -ne 0 ] ; then exit 1 ; fi
     cd .. && rm build -rf
 
     echo -e "\r\n== Compile discovery without multicast version =="
     mkdir -p build && cd build
-    cmake -DUA_ENABLE_DISCOVERY=ON -DUA_ENABLE_DISCOVERY_MULTICAST=OFF -DUA_BUILD_EXAMPLES=ON ..
+    cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/$PYTHON -DUA_ENABLE_DISCOVERY=ON -DUA_ENABLE_DISCOVERY_MULTICAST=OFF -DUA_BUILD_EXAMPLES=ON ..
     make -j
     if [ $? -ne 0 ] ; then exit 1 ; fi
     cd .. && rm build -rf
@@ -187,30 +187,31 @@ else
 
     echo -e "\r\n== Compile multithreaded version with discovery =="
     mkdir -p build && cd build
-    cmake -DUA_ENABLE_MULTITHREADING=ON -DUA_ENABLE_DISCOVERY=ON -DUA_ENABLE_DISCOVERY_MULTICAST=ON -DUA_BUILD_EXAMPLES=ON ..
+    cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/$PYTHON -DUA_ENABLE_MULTITHREADING=ON -DUA_ENABLE_DISCOVERY=ON -DUA_ENABLE_DISCOVERY_MULTICAST=ON -DUA_BUILD_EXAMPLES=ON ..
     make -j
     if [ $? -ne 0 ] ; then exit 1 ; fi
     cd .. && rm build -rf
     echo -en 'travis_fold:end:script.build.multithread\\r'
 
-    echo -e "\r\n== Debug build and unit tests (64 bit, python 2) ==" && echo -en 'travis_fold:start:script.build.unit_test_valgrind_python2\\r'
+    echo -e "\r\n== Unit tests (full NS0) ==" && echo -en 'travis_fold:start:script.build.unit_test_ns0_full\\r'
     mkdir -p build && cd build
-    # Force to use python2 to test compilation with python2
-    cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python2 -DUA_ENABLE_FULL_NS0=ON \
+    # Valgrind cannot handle the full NS0 because the generated file is too big. Thus run NS0 full without valgrind
+    cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/$PYTHON -DUA_ENABLE_FULL_NS0=ON \
     -DCMAKE_BUILD_TYPE=Debug -DUA_BUILD_EXAMPLES=ON -DUA_ENABLE_DISCOVERY=ON -DUA_ENABLE_DISCOVERY_MULTICAST=ON \
-    -DUA_BUILD_UNIT_TESTS=ON -DUA_ENABLE_COVERAGE=ON -DUA_ENABLE_VALGRIND_UNIT_TESTS=ON ..
+    -DUA_BUILD_UNIT_TESTS=ON -DUA_ENABLE_COVERAGE=OFF -DUA_ENABLE_VALGRIND_UNIT_TESTS=OFF ..
     make -j && make test ARGS="-V"
     if [ $? -ne 0 ] ; then exit 1 ; fi
     cd .. && rm build -rf
-    echo -en 'travis_fold:end:script.build.unit_test_valgrind_python2\\r'
+    echo -en 'travis_fold:end:script.build.unit_test_ns0\\r'
 
-    echo -e "\r\n== Debug build and unit tests (64 bit, python 3) ==" && echo -en 'travis_fold:start:script.build.unit_test_valgrind_python3\\r'
+    echo -e "\r\n== Unit tests (minimal NS0) ==" && echo -en 'travis_fold:start:script.build.unit_test_ns0_minimal\\r'
     mkdir -p build && cd build
-    # Force to use python3 to test compilation with python3
-    cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 -DCMAKE_BUILD_TYPE=Debug -DUA_BUILD_EXAMPLES=ON -DUA_ENABLE_DISCOVERY=ON -DUA_ENABLE_DISCOVERY_MULTICAST=ON -DUA_BUILD_UNIT_TESTS=ON -DUA_ENABLE_COVERAGE=ON -DUA_ENABLE_VALGRIND_UNIT_TESTS=ON ..
+    cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/$PYTHON \
+    -DCMAKE_BUILD_TYPE=Debug -DUA_BUILD_EXAMPLES=ON -DUA_ENABLE_DISCOVERY=ON -DUA_ENABLE_DISCOVERY_MULTICAST=ON \
+    -DUA_BUILD_UNIT_TESTS=ON -DUA_ENABLE_COVERAGE=ON -DUA_ENABLE_VALGRIND_UNIT_TESTS=ON ..
     make -j && make test ARGS="-V"
     if [ $? -ne 0 ] ; then exit 1 ; fi
-    echo -en 'travis_fold:end:script.build.unit_test_valgrind_python3\\r'
+    echo -en 'travis_fold:end:script.build.unit_test_ns0_minimal\\r'
 
     # only run coveralls on main repo, otherwise it fails uploading the files
     echo -e "\r\n== -> Current repo: ${TRAVIS_REPO_SLUG} =="