Browse Source

Fix varint serialization

- Implement varint serialization for sint32/64 uint32/64
- Fix serialization for non-signed int fields
- Implement and update related tests
Alexey Edelev 6 years ago
parent
commit
a5f1070ea9
2 changed files with 823 additions and 24 deletions
  1. 51 19
      src/lib/protobufobject.h
  2. 772 5
      tests/serializationtest.cpp

+ 51 - 19
src/lib/protobufobject.h

@@ -95,10 +95,31 @@ public:
         qProtoDebug() << __func__ << "propertyValue" << propertyValue << "fieldIndex" << fieldIndex << "typeName" << typeName;
         QByteArray result;
         WireTypes type = UnknownWireType;
+        int resultSize = result.size();
         switch (static_cast<QMetaType::Type>(propertyValue.type())) {
         case QMetaType::Int:
             type = Varint;
-            result.append(serializeVarint(propertyValue.toInt()));
+            if (typeName == "sint32"
+                    || typeName == "qtprotobuf::sint32") {
+                result.append(serializeVarintZigZag(propertyValue.toInt()));
+            } else {
+                result.append(serializeVarint(propertyValue.toLongLong()));
+            }
+            if (resultSize == result.size()) {
+                fieldIndex = NotUsedFieldIndex;
+            }
+            break;
+        case QMetaType::LongLong:
+            type = Varint;
+            if (typeName == "sint64"
+                    || typeName == "qtprotobuf::sint64") {
+                result.append(serializeVarintZigZag(propertyValue.toLongLong()));
+            } else {
+                result.append(serializeVarint(propertyValue.toLongLong()));
+            }
+            if (resultSize == result.size()) {
+                fieldIndex = NotUsedFieldIndex;
+            }
             break;
         case QMetaType::Float:
             type = Fixed32;
@@ -137,6 +158,9 @@ public:
                 type = Varint;
                 result.append(serializeVarint(propertyValue.toUInt()));
             }
+            if (resultSize == result.size()) {
+                fieldIndex = NotUsedFieldIndex;
+            }
             break;
         case QMetaType::ULongLong:
             if (typeName == "fint64"
@@ -147,6 +171,9 @@ public:
                 type = Varint;
                 result.append(serializeVarint(propertyValue.toULongLong()));
             }
+            if (resultSize == result.size()) {
+                fieldIndex = NotUsedFieldIndex;
+            }
             break;
         default:
             Q_ASSERT_X(false, staticMetaObject.className(), "Serialization of unknown type is impossible");
@@ -161,7 +188,7 @@ public:
     QByteArray serializeLengthDelimited(const QByteArray &data) const {
         qProtoDebug() << __func__ << "data.size" << data.size() << "data" << data.toHex();
         //Varint serialize field size and apply result as starting point
-        QByteArray result = serializeVarint(static_cast<unsigned int>(data.size()));
+        QByteArray result = serializeVarintZero(static_cast<unsigned int>(data.size()));
         result.append(data);
         return result;
     }
@@ -208,10 +235,10 @@ public:
 
         QByteArray serializedList;
         for(auto& value : listValue) {
-            serializedList.append(serializeVarintZZ(value));
+            serializedList.append(serializeVarintZigZag(value));
         }
         //If internal field type is not LengthDelimited, exact amount of fields to be specified
-        serializedList.prepend(serializeVarint(static_cast<unsigned int>(serializedList.size())));
+        serializedList.prepend(serializeVarintZero(static_cast<unsigned int>(serializedList.size())));
         return serializedList;
     }
 
@@ -229,7 +256,7 @@ public:
             serializedList.append(serializeFixed(value));
         }
         //If internal field type is not LengthDelimited, exact amount of fields to be specified
-        serializedList.prepend(serializeVarint(static_cast<unsigned int>(serializedList.size())));
+        serializedList.prepend(serializeVarintZero(static_cast<unsigned int>(serializedList.size())));
         return serializedList;
     }
 
@@ -289,20 +316,12 @@ public:
               typename std::enable_if_t<std::is_signed<V>::value, int> = 0>
     QByteArray serializeVarint(V value) const {
         qProtoDebug() << __func__ << "value" << value;
-        UV uValue = 0;
-        //Use ZigZag convertion first and apply unsigned variant next
-        if (value < 0) {
-            value = (value << 1) ^ (value >> (sizeof(UV) * 8 - 1));
-            uValue = *(UV *)&value;
-        } else {
-            uValue = static_cast<UV>(value);
-        }
-        return serializeVarint(uValue);
+        return serializeVarint(static_cast<UV>(value));
     }
 
     template <typename V, typename UV = typename std::make_unsigned<V>::type,
               typename std::enable_if_t<std::is_signed<V>::value, int> = 0>
-    QByteArray serializeVarintZZ(V value) const {
+    QByteArray serializeVarintZigZag(V value) const {
         qProtoDebug() << __func__ << "value" << value;
         UV uValue = 0;
 
@@ -326,16 +345,29 @@ public:
             value >>= 7;
         }
 
-        //Zero case
-        if (result.isEmpty()) {
-            result.append('\0');
-        }
+        //TODO: Zero case.
+        //Aligned to reference cpp implementation. Where 0 ignored.
+        //if (result.isEmpty()) {
+        //    result.append('\0');
+        //}
 
         //Mark last chunk as last
         result.data()[result.size() - 1] &= ~0x80;
         return result;
     }
 
+    template <typename V,
+              typename std::enable_if_t<std::is_unsigned<V>::value, int> = 0>
+    QByteArray serializeVarintZero(V value) const {
+        qProtoDebug() << __func__ << "value" << value;
+        QByteArray result = serializeVarint(value);
+        //Zero case.
+        if (result.isEmpty()) {
+            result.append('\0');
+        }
+        return result;
+    }
+
 //####################################################
 //               Deserialization
 //####################################################

+ 772 - 5
tests/serializationtest.cpp

@@ -26,6 +26,11 @@
 #include "serializationtest.h"
 
 #include "simpleintmessage.h"
+#include "simpleuintmessage.h"
+#include "simplesintmessage.h"
+#include "simpleint64message.h"
+#include "simpleuint64message.h"
+#include "simplesint64message.h"
 #include "simplefixedint32message.h"
 #include "simplefixedint64message.h"
 #include "simplefloatmessage.h"
@@ -75,9 +80,7 @@ TEST_F(SerializationTest, IntMessageSerializeTest)
 
     test.setTestFieldInt(0);
     result = test.serialize();
-    ASSERT_EQ(result.size(), 2);
-    ASSERT_EQ(result.at(0), 0x08);
-    ASSERT_EQ(result.at(1), '\x00');
+    ASSERT_EQ(result.size(), 0);
 
     test.setTestFieldInt(INT8_MAX + 1);
     result = test.serialize();
@@ -118,6 +121,264 @@ TEST_F(SerializationTest, IntMessageSerializeTest)
     ASSERT_EQ(result.at(4), '\xff');
     ASSERT_EQ(result.at(5), '\x07');
 
+    test.setTestFieldInt(-1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(-462);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xb2');
+    ASSERT_EQ(result.at(2), '\xfc');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(-63585);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x9f');
+    ASSERT_EQ(result.at(2), '\x8f');
+    ASSERT_EQ(result.at(3), '\xfc');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(INT8_MIN);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(INT16_MIN);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\xfe');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(INT32_MIN);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x80');
+    ASSERT_EQ(result.at(4), '\x80');
+    ASSERT_EQ(result.at(5), '\xf8');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(INT8_MIN - 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xfe');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(INT16_MIN - 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xfd');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+}
+
+TEST_F(SerializationTest, UIntMessageSerializeTest)
+{
+    SimpleUIntMessage test;
+    test.setTestFieldInt(15);
+    QByteArray result = test.serialize();
+    ASSERT_EQ(result.size(), 2);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x0f');
+
+    test.setTestFieldInt(300);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xac');
+    ASSERT_EQ(result.at(2), '\x02');
+
+    test.setTestFieldInt(65545);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x89');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x04');
+
+    test.setTestFieldInt(0);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 0);
+
+    test.setTestFieldInt(UINT8_MAX + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x02');
+
+    test.setTestFieldInt(UINT16_MAX + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x04');
+
+    test.setTestFieldInt(UINT8_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\x01');
+
+    test.setTestFieldInt(UINT16_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\x03');
+
+    test.setTestFieldInt(UINT32_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 6);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\x0f');
+}
+
+TEST_F(SerializationTest, SIntMessageSerializeTest)
+{
+    SimpleSIntMessage test;
+    test.setTestFieldInt(15);
+    QByteArray result = test.serialize();
+    ASSERT_EQ(result.size(), 2);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x1e');
+
+    test.setTestFieldInt(300);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xd8');
+    ASSERT_EQ(result.at(2), '\x04');
+
+    test.setTestFieldInt(65545);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x92');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x08');
+
+    test.setTestFieldInt(0);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 0);
+
+    test.setTestFieldInt(INT8_MAX + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x02');
+
+    test.setTestFieldInt(INT16_MAX + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x04');
+
+    test.setTestFieldInt(INT8_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xfe');
+    ASSERT_EQ(result.at(2), '\x01');
+
+    test.setTestFieldInt(INT16_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xfe');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\x03');
+
+    test.setTestFieldInt(INT32_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 6);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xfe');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\x0f');
+
     test.setTestFieldInt(-1);
     result = test.serialize();
     ASSERT_EQ(result.size(), 2);
@@ -180,6 +441,512 @@ TEST_F(SerializationTest, IntMessageSerializeTest)
     ASSERT_EQ(result.at(3), '\x04');
 }
 
+TEST_F(SerializationTest, Int64MessageSerializeTest)
+{
+    SimpleInt64Message test;
+    test.setTestFieldInt(15);
+    QByteArray result = test.serialize();
+    ASSERT_EQ(result.size(), 2);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x0f');
+
+    test.setTestFieldInt(300);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xac');
+    ASSERT_EQ(result.at(2), '\x02');
+
+    test.setTestFieldInt(65545);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x89');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x04');
+
+    test.setTestFieldInt(0);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 0);
+
+    test.setTestFieldInt(INT8_MAX + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x01');
+
+    test.setTestFieldInt(INT16_MAX + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x02');
+
+    test.setTestFieldInt((qlonglong)(INT32_MAX) + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 6);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x80');
+    ASSERT_EQ(result.at(4), '\x80');
+    ASSERT_EQ(result.at(5), '\x08');
+
+    test.setTestFieldInt(INT8_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 2);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x7f');
+
+    test.setTestFieldInt(INT16_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\x01');
+
+    test.setTestFieldInt(INT32_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 6);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\x07');
+
+    test.setTestFieldInt(INT64_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 10);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\x7f');
+
+    test.setTestFieldInt(-1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(-462);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xb2');
+    ASSERT_EQ(result.at(2), '\xfc');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(-63585);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x9f');
+    ASSERT_EQ(result.at(2), '\x8f');
+    ASSERT_EQ(result.at(3), '\xfc');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(INT8_MIN);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(INT16_MIN);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\xfe');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(INT32_MIN);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x80');
+    ASSERT_EQ(result.at(4), '\x80');
+    ASSERT_EQ(result.at(5), '\xf8');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(INT8_MIN - 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xfe');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(INT16_MIN - 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xfd');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt((qlonglong)INT32_MIN - 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xf7');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(INT64_MIN);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x80');
+    ASSERT_EQ(result.at(4), '\x80');
+    ASSERT_EQ(result.at(5), '\x80');
+    ASSERT_EQ(result.at(6), '\x80');
+    ASSERT_EQ(result.at(7), '\x80');
+    ASSERT_EQ(result.at(8), '\x80');
+    ASSERT_EQ(result.at(9), '\x80');
+    ASSERT_EQ(result.at(10), '\x01');
+}
+
+TEST_F(SerializationTest, UInt64MessageSerializeTest)
+{
+    SimpleUInt64Message test;
+    test.setTestFieldInt(15);
+    QByteArray result = test.serialize();
+    ASSERT_EQ(result.size(), 2);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x0f');
+
+    test.setTestFieldInt(300);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xac');
+    ASSERT_EQ(result.at(2), '\x02');
+
+    test.setTestFieldInt(65545);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x89');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x04');
+
+    test.setTestFieldInt(0);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 0);
+
+    test.setTestFieldInt(UINT8_MAX + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x02');
+
+    test.setTestFieldInt(UINT16_MAX + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x04');
+
+    test.setTestFieldInt((qulonglong)UINT32_MAX + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 6);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x80');
+    ASSERT_EQ(result.at(4), '\x80');
+    ASSERT_EQ(result.at(5), '\x10');
+
+    test.setTestFieldInt(UINT8_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\x01');
+
+    test.setTestFieldInt(UINT16_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\x03');
+
+    test.setTestFieldInt(UINT32_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 6);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\x0f');
+
+    test.setTestFieldInt(UINT64_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+}
+
+TEST_F(SerializationTest, SInt64MessageSerializeTest)
+{
+    SimpleSInt64Message test;
+    test.setTestFieldInt(15);
+    QByteArray result = test.serialize();
+    ASSERT_EQ(result.size(), 2);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x1e');
+
+    test.setTestFieldInt(300);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xd8');
+    ASSERT_EQ(result.at(2), '\x04');
+
+    test.setTestFieldInt(65545);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x92');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x08');
+
+    test.setTestFieldInt(0);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 0);
+
+    test.setTestFieldInt(INT8_MAX + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x02');
+
+    test.setTestFieldInt(INT16_MAX + 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x80');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x04');
+
+    test.setTestFieldInt(INT8_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xfe');
+    ASSERT_EQ(result.at(2), '\x01');
+
+    test.setTestFieldInt(INT16_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xfe');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\x03');
+
+    test.setTestFieldInt(INT32_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 6);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xfe');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\x0f');
+
+    test.setTestFieldInt(INT64_MAX);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xfe');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(-1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 2);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x01');
+
+    test.setTestFieldInt(-462);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x9b');
+    ASSERT_EQ(result.at(2), '\x07');
+
+    test.setTestFieldInt(-63585);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xc1');
+    ASSERT_EQ(result.at(2), '\xe1');
+    ASSERT_EQ(result.at(3), '\x07');
+
+    test.setTestFieldInt(INT8_MIN);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\x01');
+
+    test.setTestFieldInt(INT16_MIN);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\x03');
+
+    test.setTestFieldInt(INT32_MIN);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 6);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\x0f');
+
+    test.setTestFieldInt(INT64_MIN);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 11);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xff');
+    ASSERT_EQ(result.at(2), '\xff');
+    ASSERT_EQ(result.at(3), '\xff');
+    ASSERT_EQ(result.at(4), '\xff');
+    ASSERT_EQ(result.at(5), '\xff');
+    ASSERT_EQ(result.at(6), '\xff');
+    ASSERT_EQ(result.at(7), '\xff');
+    ASSERT_EQ(result.at(8), '\xff');
+    ASSERT_EQ(result.at(9), '\xff');
+    ASSERT_EQ(result.at(10), '\x01');
+
+    test.setTestFieldInt(INT8_MIN - 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x81');
+    ASSERT_EQ(result.at(2), '\x02');
+
+    test.setTestFieldInt(INT16_MIN - 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x81');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x04');
+
+    test.setTestFieldInt((qlonglong)INT32_MIN - 1);
+    result = test.serialize();
+    ASSERT_EQ(result.size(), 6);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x81');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x80');
+    ASSERT_EQ(result.at(4), '\x80');
+    ASSERT_EQ(result.at(5), '\x10');
+}
+
 TEST_F(SerializationTest, FixedInt32MessageSerializeTest)
 {
     constexpr int Fixed32MessageSize = 5;
@@ -453,8 +1220,8 @@ TEST_F(SerializationTest, ComplexTypeSerializeTest)
     result = test.serialize();
     //qDebug() << "result" << result.toHex();
 
-    ASSERT_TRUE(result == QByteArray::fromHex("120832067177657274790859")
-                || result == QByteArray::fromHex("085912083206717765727479"));
+    ASSERT_TRUE(result == QByteArray::fromHex("1208320671776572747908d3ffffffffffffffff01")
+                || result == QByteArray::fromHex("08d3ffffffffffffffff0112083206717765727479"));
 }
 
 TEST_F(SerializationTest, RepeatedIntMessageTest)