Kaynağa Gözat

Initial setup of the WireFormatter with unit tests.

Bart Hertog 6 yıl önce
ebeveyn
işleme
8ed5c88e31
4 değiştirilmiş dosya ile 155 ekleme ve 0 silme
  1. 18 0
      CMakeLists.txt
  2. 56 0
      src/WireFormatter.h
  3. 74 0
      test/test_WireFormatter.cpp
  4. 7 0
      test/test_main.cpp

+ 18 - 0
CMakeLists.txt

@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 3.10)
+
+project(test_EmbeddedProto)
+
+set(CMAKE_CXX_FLAGS "-std=c++14 -Wall")
+
+
+add_subdirectory(googletest)
+
+file(GLOB src_files
+    "test/*.cpp"
+)
+
+include_directories(test src)
+include_directories(googletest/googletest googletest/googletest/include)
+
+add_executable(test_EmbeddedProto ${src_files})
+target_link_libraries(test_EmbeddedProto gtest)

+ 56 - 0
src/WireFormatter.h

@@ -0,0 +1,56 @@
+
+#ifndef _WIRE_FORMATTER_H_
+#define _WIRE_FORMATTER_H_
+
+#include <cstdint>
+
+namespace EmbeddedProto 
+{
+namespace WireFormatter 
+{
+  
+  enum class WireType 
+  {
+    VARINT            = 0,  //!< int32, int64, uint32, uint64, sint32, sint64, bool, enum.
+    FIXED64           = 1,  //!< fixed64, sfixed64, double
+    LENGTH_DELIMITED  = 2,  //!< string, bytes, embedded messages, packed repeated fields
+    START_GROUP       = 3,  //!< Depricated
+    END_GROUP         = 4,  //!< Depricated
+    FIXED32           = 5,  //!< fixed32, sfixed32, float
+  };
+
+  //! Create the tag of a field. This is the combination of field number by three and wire type.
+  /*!
+    The field number is shifted to the left by three bits. This creates space to or the wire type
+    of the designated field.
+  */
+  static constexpr uint32_t MakeTag(const uint32_t field_number, const WireType type)
+  {
+    return ((static_cast<uint32_t>(field_number) << 3) | static_cast<uint32_t>(type));
+  }
+
+  //! This function converts a given value int a varint formated data array.
+  /*!
+    \param[in] value  The data to be serialized.
+    \param[in] target Pointer to the first element of an array in which the data is to be serialized.
+    \warning There should be sufficient space in the array to store a varint32.
+    \return A pointer to the first byte after the data just serialized.
+    This code is copied and modified from google protobuf sources.
+  */
+  static constexpr uint8_t* WriteVarint32ToArray(uint32_t value, uint8_t* target) {
+    constexpr uint32_t MSB_BYTE = 0x00000080;
+    constexpr uint8_t SHIFT_N_BITS = 7;
+
+    while (value >= MSB_BYTE) {
+      *target = static_cast<uint8_t>(value | MSB_BYTE);
+      value >>= SHIFT_N_BITS;
+      ++target;
+    }
+    *target = static_cast<uint8_t>(value);
+    return target + 1;
+  }
+
+
+} // End of namespace WireFormatter.
+} // End of namespace EmbeddedProto.
+#endif

+ 74 - 0
test/test_WireFormatter.cpp

@@ -0,0 +1,74 @@
+
+
+#include "gtest/gtest.h"
+
+#include <WireFormatter.h>
+#include <cstdint>    
+#include <limits> 
+
+namespace test_EmbeddedAMS_WireFormatter 
+{
+
+TEST(WireFormatter, MakeTag)
+{
+  // Varints
+  EXPECT_EQ(0x0000, ::EmbeddedProto::WireFormatter::MakeTag(0, ::EmbeddedProto::WireFormatter::WireType::VARINT));
+  EXPECT_EQ(0x0008, ::EmbeddedProto::WireFormatter::MakeTag(1, ::EmbeddedProto::WireFormatter::WireType::VARINT));
+  EXPECT_EQ(0x07F8, ::EmbeddedProto::WireFormatter::MakeTag(255, ::EmbeddedProto::WireFormatter::WireType::VARINT));
+
+  // Doubles
+  EXPECT_EQ(0x0001, ::EmbeddedProto::WireFormatter::MakeTag(0, ::EmbeddedProto::WireFormatter::WireType::FIXED64));
+  EXPECT_EQ(0x0009, ::EmbeddedProto::WireFormatter::MakeTag(1, ::EmbeddedProto::WireFormatter::WireType::FIXED64));
+  EXPECT_EQ(0x07F9, ::EmbeddedProto::WireFormatter::MakeTag(255, ::EmbeddedProto::WireFormatter::WireType::FIXED64));
+
+  // Repeated fields
+  EXPECT_EQ(0x0002, ::EmbeddedProto::WireFormatter::MakeTag(0, ::EmbeddedProto::WireFormatter::WireType::LENGTH_DELIMITED));
+  EXPECT_EQ(0x000A, ::EmbeddedProto::WireFormatter::MakeTag(1, ::EmbeddedProto::WireFormatter::WireType::LENGTH_DELIMITED));
+  EXPECT_EQ(0x07FA, ::EmbeddedProto::WireFormatter::MakeTag(255, ::EmbeddedProto::WireFormatter::WireType::LENGTH_DELIMITED));
+
+  // Skip the depricated group type.
+
+  // Floats
+  EXPECT_EQ(0x0005, ::EmbeddedProto::WireFormatter::MakeTag(0, ::EmbeddedProto::WireFormatter::WireType::FIXED32));
+  EXPECT_EQ(0x000D, ::EmbeddedProto::WireFormatter::MakeTag(1, ::EmbeddedProto::WireFormatter::WireType::FIXED32));
+  EXPECT_EQ(0x07FD, ::EmbeddedProto::WireFormatter::MakeTag(255, ::EmbeddedProto::WireFormatter::WireType::FIXED32));
+}
+
+TEST(WireFormatter, WriteVarint32ToArray) 
+{
+
+  // There are five bytes required to encode a 32bit value, take one extra for checking the return 
+  // values.
+  uint8_t target[6]; 
+
+  EXPECT_EQ(&target[1], ::EmbeddedProto::WireFormatter::WriteVarint32ToArray(0, target));
+  EXPECT_EQ(0, target[0]);
+
+  EXPECT_EQ(&target[1], ::EmbeddedProto::WireFormatter::WriteVarint32ToArray(1, target));
+  EXPECT_EQ(1, target[0]);
+
+  // Edge case of the first byte.
+  EXPECT_EQ(&target[1], ::EmbeddedProto::WireFormatter::WriteVarint32ToArray(127, target));
+  EXPECT_EQ(127, target[0]);
+
+  // Just over the first byte.
+  EXPECT_EQ(&target[2], ::EmbeddedProto::WireFormatter::WriteVarint32ToArray(128, target));
+  EXPECT_EQ(128, target[0]);
+  EXPECT_EQ(1, target[1]);
+
+  // Full first byte.
+  EXPECT_EQ(&target[2], ::EmbeddedProto::WireFormatter::WriteVarint32ToArray(255, target));
+  EXPECT_EQ(255, target[0]);
+  EXPECT_EQ(1, target[1]);
+
+  // Fast forward to the largest possible number.
+  EXPECT_EQ(&target[5], ::EmbeddedProto::WireFormatter::WriteVarint32ToArray(std::numeric_limits<uint32_t>::max(), target));
+  EXPECT_EQ(255, target[0]);
+  EXPECT_EQ(255, target[1]);
+  EXPECT_EQ(255, target[2]);
+  EXPECT_EQ(255, target[3]);
+  EXPECT_EQ(15, target[4]);
+
+}
+
+} // End of namespace test_EmbeddedAMS_WireFormatter

+ 7 - 0
test/test_main.cpp

@@ -0,0 +1,7 @@
+#include <gtest/gtest.h>
+
+int main(int argc, char **argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
+