Add CBOR encoding and parsing tests 90/308390/38
authorJan Wojtkowski <j.wojtkowski@samsung.com>
Fri, 12 Apr 2024 10:49:59 +0000 (12:49 +0200)
committerJan Wojtkowski <j.wojtkowski@samsung.com>
Tue, 16 Apr 2024 12:45:59 +0000 (14:45 +0200)
Adjust cbor_parsing methods

Change-Id: I3274053b9a6ba8cc00bb93f60a1867a3e27eac0a

srcs/cbor_encoding.cpp
srcs/cbor_encoding.h
srcs/cbor_parsing.cpp
srcs/cbor_parsing.h
tests/cbor_tests.cpp

index 0dbe3a7a79ed4ce249959aa7a67b32bb0aeb395b..17a607b739654f988de4625d79edb4728bf9c807 100644 (file)
@@ -143,6 +143,9 @@ void Container::AppendTextStringZ(const char *value)
 {
     assert(!m_appendingToChild);
 
+    if (!value)
+        THROW_UNKNOWN("NULL value");
+
     CborError err;
     err = cbor_encode_text_stringz(&m_encoder, value);
     if (err != CborNoError)
@@ -252,8 +255,8 @@ void SortedMap::AppendTextStringAt(const Key &key, const std::string_view &value
 
 void SortedMap::AppendTextStringZAt(const Key &key, const char *value)
 {
-    assert(value);
-
+    if (!value)
+        THROW_UNKNOWN("NULL value");
     AddKey(key);
     AppendTextStringZ(value);
 }
@@ -296,14 +299,18 @@ void SortedMap::AddKey(const Key &key)
         AppendInt64(std::get<int64_t>(key));
     } else if (std::holds_alternative<std::string_view>(key)) {
         AppendTextString(std::get<std::string_view>(key));
-    } else {
+    } else if (std::holds_alternative<const char *>(key)) {
+        if (!std::get<const char *>(key))
+            THROW_UNKNOWN("NULL key");
+        AppendTextString(std::string_view{std::get<const char *>(key)});
+    } else
         THROW_UNKNOWN("Unexpected variant type");
-    }
 }
 
 Encoder Encoder::Create(uint8_t *output, size_t size)
 {
-    assert(output);
+    if (!output)
+        THROW_UNKNOWN("NULL output buffer");
     CborEncoder encoder;
     cbor_encoder_init(&encoder, output, size, 0);
     return Encoder(std::move(encoder), output);
index 26a678db7a83e501be72d411f7d1e5efc483818c..5195578f6344cfafa228917bd0b0aac83738648a 100644 (file)
@@ -83,7 +83,10 @@ private:
     Container *m_parent;
 };
 
-typedef std::variant<int64_t, std::string_view> Key;
+// const char * is for dealing with const char * arguments, since std::string_view may not be
+// sufficient if a nullptr is passed (it can lead to Segfault of the program); std::string_view can
+// handle both std::string and std::string_view arguments
+typedef std::variant<int64_t, const char *, std::string_view> Key;
 
 class SortedMap : protected Container {
 public:
index 7f3bddd1c47718a9618e98ef1e2788be6fe32fb8..80335f88b5b7e29618a86b4e6ae35103b0aecabf 100644 (file)
@@ -227,43 +227,57 @@ Buffer Container::GetByteString()
 bool SortedMap::LocateKey(const Key &key)
 {
     assert(!m_parsingChild);
-
     auto backup = m_it;
+    auto restoreIt = [&] {
+        m_it = backup; // restore the iterator
+        return false;
+    };
+
     for (;;) {
         if (cbor_value_at_end(&m_it))
-            return false;
-
+            return restoreIt(); // key not found
         if (std::holds_alternative<int64_t>(key)) {
-            auto keyInt = std::get<int64_t>(key);
-            auto tmpKey = GetInt64(); // skips key
-
-            if (tmpKey > keyInt)
-                break; // bigger key found
-
-            if (tmpKey == keyInt)
-                return true;
-        } else if (std::holds_alternative<std::string_view>(key)) {
-            auto &keyStr = std::get<std::string_view>(key);
-            auto tmpKey = GetTextString(); // skips key
-
-            if (tmpKey.size() > keyStr.size() ||
-                (tmpKey.size() == keyStr.size() && tmpKey > keyStr))
-                break; // bigger key found
-
-            if (tmpKey == keyStr)
-                return true;
+            auto intKey = std::get<int64_t>(key);
+            try {
+                int64_t tmpKey = GetInt64();
+                if (tmpKey > intKey)
+                    return restoreIt(); // bigger key found
+                if (tmpKey == intKey)
+                    return true;
+            } catch (const Exception::Unknown &) {
+                Advance(); // skip key
+            }
+        } else if (std::holds_alternative<std::string_view>(key) ||
+                   std::holds_alternative<const char *>(key)) {
+            auto strKey = [&] {
+                if (std::holds_alternative<std::string_view>(key))
+                    return std::get<std::string_view>(key);
+                auto cstrKey = std::get<const char *>(key);
+                if (!cstrKey)
+                    THROW_UNKNOWN("NULL key");
+                return std::string_view{std::get<const char *>(key)};
+            }();
+            try {
+                std::string tmpKey = GetTextString();
+                if (tmpKey.size() > strKey.size() ||
+                    (tmpKey.size() == strKey.size() && tmpKey > strKey))
+                    return restoreIt(); // bigger key found
+                if (tmpKey == strKey)
+                    return true;
+            } catch (const Exception::Unknown &) {
+                Advance(); // skip key
+            }
         } else if (std::holds_alternative<std::monostate>(key)) {
-            Advance(); // skip key
-            return true;
+            if (m_it.type == CborIntegerType || m_it.type == CborTextStringType) {
+                Advance(); // skip key
+                return true;
+            } else
+                THROW_UNKNOWN("Unsupported key type");
         } else {
             THROW_UNKNOWN("Unexpeceted variant type");
         }
-
-        // skip value
-        Advance();
+        Advance(); // skip value
     }
-    m_it = backup; // restore the iterator if key is not found
-    return false;
 }
 
 std::optional<SortedMap> SortedMap::EnterMapAt(const Key &key)
index 34d31830ca8af380a7d93e52e75445b1b0b5b9e6..3d8572125a51da8424758248c1155cf3a4161983 100644 (file)
@@ -66,7 +66,10 @@ private:
     Container *m_parent;
 };
 
-typedef std::variant<std::monostate, int64_t, std::string_view> Key;
+// const char* is for const char* arguments, since string_view is not enough because in case of
+// passing a nullptr it Segfaults the program; std::string_view is for std::string and
+// std::string_view arguments
+typedef std::variant<std::monostate, int64_t, const char *, std::string_view> Key;
 typedef std::variant<int64_t, std::string> KeyCopy;
 extern const Key CURRENT_KEY;
 
index 68aaa5ac42aecc6b2e5df0bf4b09c94985441584..77ad9efd10961eae3e4e70736e2a1375d71203ce 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include "cbor_encoding.h"
+#include "cbor_parsing.h"
 #include "common.h"
 #include "crypto/common.h"
 #include "exception.h"
@@ -27,6 +28,9 @@
 #include <webauthn-types.h>
 #include <webauthn.h>
 
+using Exception::EncodingFailed;
+using Exception::Unknown;
+
 namespace {
 
 struct date {
@@ -71,6 +75,56 @@ const CryptoBuffer SECRET_EXAMPLE_2 = {
 const Hint GA = {'g', 'a'};
 const Hint MC = {'m', 'c'};
 
+constexpr inline int64_t INT64_VALUES[] = {0,
+                                           1,
+                                           10,
+                                           23,
+                                           24,
+                                           25,
+                                           100,
+                                           10000,
+                                           1'000'000,
+                                           10'000'000,
+                                           std::numeric_limits<int64_t>::max(),
+                                           std::numeric_limits<int64_t>::min(),
+                                           -1'000'000,
+                                           -10000,
+                                           -100,
+                                           -25,
+                                           -24,
+                                           -23,
+                                           -10,
+                                           -1};
+
+constexpr inline bool BOOL_VALUES[] = {true, false};
+
+const Buffer BYTE_STRING_VALUE = {0x83,
+                                  0x03,
+                                  0x6B,
+                                  0x73,
+                                  0x6F,
+                                  0x6D,
+                                  0x65,
+                                  0x20,
+                                  0x73,
+                                  0x74,
+                                  0x72,
+                                  0x69,
+                                  0x6E,
+                                  0x67,
+                                  0x83,
+                                  0x04,
+                                  0x05,
+                                  0x06};
+
+constexpr inline std::string_view STRING_VIEW_VALUES[] = {
+    "Fusce",     "congue",   "maximus",   "at",       "lobortis", "Nulla",     "feugiat",
+    "arcu",      "quis",     "arcu",      "faucibus", "a",        "tincidunt", "tellus",
+    "malesuada", "Nam",      "vel",       "commodo",  "eros",     "nec",       "bibendum",
+    "est",       "Fusce",    "pulvinar",  "mauris",   "ac",       "lorem",     "sodales",
+    "eu",        "pulvinar", "turpis",    "maximus",  "Quisque",  "suscipit",  "est",
+    "sed",       "ante",     "dignissim", "et",       "finibus",  "orci",      "viverra"};
+
 struct tm convertToTm(struct date &date)
 {
     struct tm ret;
@@ -217,3 +271,1738 @@ TEST(CborEncoding, EmptyBuffers)
     buffer.size = 10;
     ASSERT_THROW(map.AppendByteStringAt(0x04, buffer), Exception::InvalidParam);
 }
+
+TEST(Cbor, MapInt64EncodingAndDecoding)
+{
+    Buffer buffer(78);
+    static constexpr size_t MAP_SIZE = std::extent_v<decltype(INT64_VALUES)>;
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(MAP_SIZE);
+        for (size_t i = 0; i < MAP_SIZE; i++)
+            EXPECT_NO_THROW(map.AppendInt64At(i, INT64_VALUES[i]));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserMap = parser.EnterMap();
+
+    for (size_t i = 0; i < MAP_SIZE; i++)
+        EXPECT_EQ(parserMap.GetInt64At(i).value(), INT64_VALUES[i]);
+}
+
+TEST(Cbor, MapBoolEncodingAndDecoding)
+{
+    Buffer buffer(5);
+    static constexpr size_t MAP_SIZE = std::extent_v<decltype(BOOL_VALUES)>;
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(MAP_SIZE);
+        for (size_t i = 0; i < MAP_SIZE; i++)
+            EXPECT_NO_THROW(map.AppendBooleanAt(i, BOOL_VALUES[i]));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserMap = parser.EnterMap();
+
+    for (size_t i = 0; i < MAP_SIZE; i++)
+        EXPECT_EQ(parserMap.GetBooleanAt(i).value(), BOOL_VALUES[i]);
+}
+
+TEST(Cbor, MapByteStringEncodingAndDecoding)
+{
+    Buffer buffer(21);
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(1);
+        EXPECT_NO_THROW(map.AppendByteStringAt(0, BYTE_STRING_VALUE));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserMap = parser.EnterMap();
+
+    EXPECT_EQ(parserMap.GetByteStringAt(0).value(), BYTE_STRING_VALUE);
+
+    Buffer buffer2(21);
+    wauthn_const_buffer_s wauthnConstBuffer;
+    wauthnConstBuffer.data = BYTE_STRING_VALUE.data();
+    wauthnConstBuffer.size = BYTE_STRING_VALUE.size();
+    auto wauthnEncoder = CborEncoding::Encoder::Create(buffer2.data(), buffer2.size());
+    {
+        auto map = wauthnEncoder.OpenMap(1);
+        EXPECT_NO_THROW(map.AppendByteStringAt(1, wauthnConstBuffer));
+    }
+
+    EXPECT_EQ(wauthnEncoder.GetBufferSize(), buffer2.size());
+
+    auto wauthnParser = CborParsing::Parser::Create(buffer2.data(), buffer2.size());
+    auto wauthnParserMap = wauthnParser.EnterMap();
+
+    EXPECT_EQ(wauthnParserMap.GetByteStringAt(1), BYTE_STRING_VALUE);
+}
+
+TEST(Cbor, MapStringZEncodingAndDecoding)
+{
+    Buffer buffer(330);
+    const size_t MAP_SIZE = std::extent_v<decltype(STRING_VIEW_VALUES)>;
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(MAP_SIZE);
+        for (size_t i = 0; i < MAP_SIZE; i++)
+            EXPECT_NO_THROW(map.AppendTextStringZAt(i, STRING_VIEW_VALUES[i].data()));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserMap = parser.EnterMap();
+
+    for (size_t i = 0; i < MAP_SIZE; i++)
+        EXPECT_EQ(parserMap.GetTextStringAt(i).value(), STRING_VIEW_VALUES[i]);
+}
+
+TEST(Cbor, ArrayStringEncodingAndDecoding)
+{
+    Buffer buffer(270);
+    static constexpr size_t ARRAY_SIZE = std::extent_v<decltype(STRING_VIEW_VALUES)>;
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto array = encoder.OpenArray(ARRAY_SIZE);
+        for (size_t i = 0; i < ARRAY_SIZE; i++)
+            EXPECT_NO_THROW(array.AppendTextString(STRING_VIEW_VALUES[i]));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserArray = parser.EnterArray();
+
+    for (size_t i = 0; i < ARRAY_SIZE; i++)
+        EXPECT_EQ(parserArray.GetTextString(), STRING_VIEW_VALUES[i]);
+}
+
+TEST(Cbor, MapOptionalTextStringEncodingAndDecoding)
+{
+    Buffer buffer(330);
+    static constexpr size_t MAP_SIZE = std::extent_v<decltype(STRING_VIEW_VALUES)>;
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(MAP_SIZE);
+        map.AppendOptionalTextStringZAt(-1, nullptr);
+        for (size_t i = 0; i < MAP_SIZE; i++)
+            EXPECT_NO_THROW(map.AppendOptionalTextStringZAt(i, STRING_VIEW_VALUES[i].data()));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserMap = parser.EnterMap();
+
+    EXPECT_EQ(parserMap.GetTextStringAt(-1), std::nullopt);
+    for (size_t i = 0; i < MAP_SIZE; i++)
+        EXPECT_EQ(parserMap.GetTextStringAt(i).value(), STRING_VIEW_VALUES[i].data());
+}
+
+TEST(Cbor, EncodingToNullBuffer)
+{
+    std::vector<uint8_t> emptyBuffer(0);
+    ASSERT_THROW(CborEncoding::Encoder::Create(emptyBuffer.data(), emptyBuffer.size()), Unknown);
+}
+
+TEST(Cbor, EmptyStringEncoding)
+{
+    std::vector<uint8_t> buffer(3);
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(2);
+        ASSERT_THROW(map.AppendTextStringZAt(1, nullptr), Unknown);
+        ASSERT_NO_THROW(map.AppendTextStringZAt(2, ""));
+    }
+}
+
+TEST(Cbor, MapDecodingValuesOfDifferentTypeThanExpected)
+{
+    Buffer buffer(24);
+    static constexpr bool BOOL_VALUE = true;
+    static constexpr int64_t INT64T_VALUE = 117;
+    static constexpr char STRING_VALUE[] = "characters";
+    const Buffer BYTE_STRING_VALUE = {0x86, 0x33, 0x45, 0x17};
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(4);
+        EXPECT_NO_THROW(map.AppendBooleanAt(0, BOOL_VALUE));
+        EXPECT_NO_THROW(map.AppendInt64At(1, INT64T_VALUE));
+        EXPECT_NO_THROW(map.AppendTextStringZAt(2, STRING_VALUE));
+        EXPECT_NO_THROW(map.AppendByteStringAt(3, BYTE_STRING_VALUE));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserMap = parser.EnterMap();
+
+    ASSERT_THROW(parserMap.GetByteStringAt(0), Unknown);
+    EXPECT_EQ(parserMap.GetTextStringAt(1), std::nullopt);
+    EXPECT_EQ(parserMap.GetInt64At(2), std::nullopt);
+    EXPECT_EQ(parserMap.GetUint64At(2), std::nullopt);
+    EXPECT_EQ(parserMap.GetBooleanAt(3), std::nullopt);
+}
+
+TEST(Cbor, DecodingMapWithNotSortedKeysFails)
+{
+    Buffer buffer(19);
+    static constexpr int64_t INT64T_VALUE = 117;
+    static constexpr char STRING_VALUE[] = "text";
+    const Buffer BYTE_STRING_VALUE = {0x86, 0x33, 0x45, 0x17};
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(3);
+        EXPECT_NO_THROW(map.AppendInt64At(0x66, INT64T_VALUE));
+        EXPECT_NO_THROW(map.AppendTextStringZAt(0x33, STRING_VALUE));
+        EXPECT_NO_THROW(map.AppendByteStringAt(0x24, BYTE_STRING_VALUE));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    ASSERT_THROW(CborParsing::Parser::Create(buffer.data(), buffer.size()), Unknown);
+}
+
+TEST(Cbor, DecodingMapWithDuplicatedKeysFails)
+{
+    Buffer buffer(7);
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(2);
+        EXPECT_NO_THROW(map.AppendInt64At(0x12, 111));
+        EXPECT_NO_THROW(map.AppendInt64At(0x12, 199));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    ASSERT_THROW(CborParsing::Parser::Create(buffer.data(), buffer.size()), Unknown);
+}
+
+TEST(Cbor, MapWithKeysOfDifferentTypesEncodingAndDecoding)
+{
+    Buffer buffer(15);
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(4);
+        EXPECT_NO_THROW(map.AppendInt64At(1, 11));
+        EXPECT_NO_THROW(map.AppendInt64At(2, 12));
+        EXPECT_NO_THROW(map.AppendInt64At("one", 13));
+        EXPECT_NO_THROW(map.AppendInt64At("two", 14));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserMap = parser.EnterMap();
+
+    EXPECT_EQ(parserMap.GetInt64At(1), 11);
+    EXPECT_EQ(parserMap.GetInt64At(2), 12);
+    EXPECT_EQ(parserMap.GetInt64At("one"), 13);
+    EXPECT_EQ(parserMap.GetInt64At("two"), 14);
+}
+
+TEST(Cbor, ReadingMapOutOfOrder)
+{
+    Buffer buffer(15);
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(4);
+        EXPECT_NO_THROW(map.AppendInt64At(1, 15));
+        EXPECT_NO_THROW(map.AppendInt64At(2, 16));
+        EXPECT_NO_THROW(map.AppendInt64At("one", 13));
+        EXPECT_NO_THROW(map.AppendInt64At("two", 14));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserMap = parser.EnterMap();
+
+    EXPECT_EQ(parserMap.GetInt64At(1), 15);
+    EXPECT_EQ(parserMap.GetInt64At(2), 16);
+    EXPECT_EQ(parserMap.GetInt64At("two"), 14);
+    EXPECT_EQ(parserMap.GetInt64At("one"), std::nullopt);
+}
+
+TEST(Cbor, DecodingMissingMapKeys)
+{
+    Buffer buffer(4);
+    static constexpr int64_t INT64T_VALUE = 117;
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(1);
+        EXPECT_NO_THROW(map.AppendInt64At(1, INT64T_VALUE));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserMap = parser.EnterMap();
+
+    EXPECT_EQ(parserMap.GetInt64At(3), std::nullopt);
+}
+
+TEST(Cbor, MapDecodingDifferentKeyType)
+{
+    Buffer buffer(11);
+    static constexpr int64_t INT64T_VALUE = 127;
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(1);
+        EXPECT_NO_THROW(map.AppendInt64At("passkey", INT64T_VALUE));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserMap = parser.EnterMap();
+
+    EXPECT_EQ(parserMap.GetInt64At(0), std::nullopt);
+    EXPECT_EQ(parserMap.GetInt64At("passkey"), INT64T_VALUE);
+}
+
+TEST(CborParsing, SortedMapPeekAndLocateKey)
+{
+    Buffer buffer(9);
+    static constexpr int KEY = 16;
+    static constexpr int VALUE = 16;
+    static constexpr std::string_view TEXT = "text";
+
+    CborEncoder encoder, mapEncoder;
+    ASSERT_NO_THROW(cbor_encoder_init(&encoder, buffer.data(), buffer.size(), 0));
+    ASSERT_NO_THROW(cbor_encoder_create_map(&encoder, &mapEncoder, 2));
+    ASSERT_NO_THROW(cbor_encode_int(&mapEncoder, KEY));
+    ASSERT_NO_THROW(cbor_encode_text_string(&mapEncoder, TEXT.data(), TEXT.size()));
+    ASSERT_NO_THROW(cbor_encode_null(&mapEncoder));
+    ASSERT_NO_THROW(cbor_encode_int(&mapEncoder, VALUE));
+    ASSERT_NO_THROW(cbor_encoder_close_container(&encoder, &mapEncoder));
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto map = parser.EnterMap();
+    EXPECT_EQ(std::get<int64_t>(map.PeekKey()), 16);
+    EXPECT_EQ(map.GetTextStringAt(16), TEXT);
+    ASSERT_THROW(map.PeekKey(), Unknown);
+    EXPECT_EQ(map.GetInt64At("test"), std::nullopt);
+    ASSERT_THROW(map.PeekKey(), Unknown);
+}
+
+TEST(Cbor, SkippingUnknownKeysWhileDecodingMap)
+{
+    Buffer buffer(23);
+    static constexpr int64_t INT64T_VALUE = 64;
+    static constexpr char STRING_VALUE[] = "string_value";
+    const Buffer BYTE_STRING_VALUE = {0x27, 0x48, 0x75};
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(3);
+        EXPECT_NO_THROW(map.AppendInt64At(0x00, INT64T_VALUE));
+        EXPECT_NO_THROW(map.AppendTextStringZAt(0x02, STRING_VALUE));
+        EXPECT_NO_THROW(map.AppendByteStringAt(0x03, BYTE_STRING_VALUE));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserMap = parser.EnterMap();
+
+    EXPECT_EQ(parserMap.GetInt64At(0x64), std::nullopt);
+    EXPECT_EQ(parserMap.GetTextStringAt("key"), std::nullopt);
+
+    EXPECT_EQ(parserMap.GetUint64At(0x00), INT64T_VALUE);
+    EXPECT_EQ(parserMap.GetTextStringAt(0x02), STRING_VALUE);
+    EXPECT_EQ(parserMap.GetByteStringAt(0x03), BYTE_STRING_VALUE);
+}
+
+TEST(Cbor, DecodingGarbageAtEnd)
+{
+    Buffer buffer(4);
+    static constexpr int64_t VALUE = 24;
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(1);
+        EXPECT_NO_THROW(map.AppendInt64At(0x00, VALUE));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+    buffer.emplace_back(0x00);
+
+    ASSERT_THROW(CborParsing::Parser::Create(buffer.data(), buffer.size()), Unknown);
+}
+
+TEST(Cbor, DecodingMapUnknownIntKey)
+{
+    Buffer buffer(10);
+    const std::vector<int64_t> VALUES = {17, 18, 19, 40};
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(VALUES.size());
+        for (size_t i = 0; i < VALUES.size(); i++)
+            EXPECT_NO_THROW(map.AppendInt64At(i, VALUES[i]));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserMap = parser.EnterMap();
+
+    ASSERT_NO_THROW(parserMap.EnterMapAt(5));
+    EXPECT_EQ(parserMap.GetInt64At(5), std::nullopt);
+}
+
+TEST(Cbor, DecodingMapNonexistentKeys)
+{
+    Buffer buffer(26);
+    static constexpr int16_t INT64T_VALUES = -128;
+    static constexpr u_int64_t UINT64T_VALUES = 128;
+    static constexpr bool BOOL_VALUE = false;
+    static constexpr char STRING_VALUE[] = "fourtyfour";
+    const Buffer BYTE_STRING_VALUE = {0x08, 0x10, 0x12};
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(5);
+        EXPECT_NO_THROW(map.AppendInt64At(0x00, INT64T_VALUES));
+        EXPECT_NO_THROW(map.AppendInt64At(0x01, UINT64T_VALUES));
+        EXPECT_NO_THROW(map.AppendBooleanAt(0x02, BOOL_VALUE));
+        EXPECT_NO_THROW(map.AppendTextStringZAt(0x03, STRING_VALUE));
+        EXPECT_NO_THROW(map.AppendByteStringAt(0x04, BYTE_STRING_VALUE));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserMap = parser.EnterMap();
+
+    EXPECT_EQ(parserMap.GetInt64At(0x08), std::nullopt);
+    EXPECT_EQ(parserMap.GetInt64At(0x00), INT64T_VALUES);
+
+    EXPECT_EQ(parserMap.GetUint64At(0x16), std::nullopt);
+    EXPECT_EQ(parserMap.GetUint64At(0x01), UINT64T_VALUES);
+
+    EXPECT_EQ(parserMap.GetBooleanAt(0x32), std::nullopt);
+    EXPECT_EQ(parserMap.GetBooleanAt(0x02), BOOL_VALUE);
+
+    EXPECT_EQ(parserMap.GetTextStringAt(0x64), std::nullopt);
+    EXPECT_EQ(parserMap.GetTextStringAt(0x03), STRING_VALUE);
+
+    EXPECT_EQ(parserMap.GetByteStringAt(0x128), std::nullopt);
+    EXPECT_EQ(parserMap.GetByteStringAt(0x04), BYTE_STRING_VALUE);
+}
+
+TEST(Cbor, NestedStructuresEncodingAndDecoding1)
+{
+    Buffer buffer(62);
+    const std::vector<int64_t> INT64T_VALUES = {17, 18, 19, 40};
+    const std::vector<std::string_view> STRING_VALUES = {"Lorem", "ipsum", "dolores"};
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(3);
+        {
+            auto firstArray = map.OpenArrayAt(0, INT64T_VALUES.size());
+            for (auto x : INT64T_VALUES)
+                EXPECT_NO_THROW(firstArray.AppendInt64(x));
+        }
+
+        {
+            auto firstMap = map.OpenMapAt(1, STRING_VALUES.size());
+            for (size_t i = 0; i < STRING_VALUES.size(); i++)
+                EXPECT_NO_THROW(firstMap.AppendTextStringZAt("text_" + std::to_string(i),
+                                                             STRING_VALUES[i].data()));
+        }
+
+        {
+            auto secondMap = map.OpenMapAt(2, 2);
+            EXPECT_NO_THROW(secondMap.AppendBooleanAt(3, true));
+
+            auto secondArray = secondMap.OpenArrayAt(4, INT64T_VALUES.size());
+            for (auto x : INT64T_VALUES)
+                EXPECT_NO_THROW(secondArray.AppendInt64(x));
+        }
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserMap = parser.EnterMap();
+
+    {
+        auto firstArrayParser = parserMap.EnterArrayAt(0).value();
+        for (auto x : INT64T_VALUES)
+            EXPECT_EQ(firstArrayParser.GetInt64(), x);
+        ASSERT_THROW(firstArrayParser.GetInt64(), Unknown);
+    }
+
+    {
+        auto firstMapParser = parserMap.EnterMapAt(1).value();
+        EXPECT_EQ(firstMapParser.GetTextStringAt("text_0"), STRING_VALUES[0]);
+        EXPECT_EQ(firstMapParser.GetTextStringAt("text_1"), STRING_VALUES[1]);
+        EXPECT_EQ(firstMapParser.GetTextStringAt("text_2"), STRING_VALUES[2]);
+    }
+
+    {
+        auto secondMapParser = parserMap.EnterMapAt(2).value();
+        EXPECT_EQ(secondMapParser.GetBooleanAt(3), true);
+
+        auto secondArrayParser = secondMapParser.EnterArrayAt(4).value();
+        for (auto x : INT64T_VALUES)
+            EXPECT_EQ(secondArrayParser.GetInt64(), x);
+        ASSERT_THROW(secondArrayParser.GetInt64(), Unknown);
+    }
+}
+
+TEST(Cbor, NestedStructuresEncodingAndDecoding2)
+{
+    Buffer buffer(56);
+    const std::vector<int64_t> INT64T_VALUES = {33, 11, 93, 39};
+    const std::vector<std::string_view> STRING_VALUES = {"edoras", "nimrais", "dimholt"};
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto array = encoder.OpenArray(6);
+        for (auto x : INT64T_VALUES)
+            EXPECT_NO_THROW(array.AppendInt64(x));
+
+        {
+            auto nestedMap = array.OpenMap(STRING_VALUES.size() + 1);
+            for (size_t i = 0; i < STRING_VALUES.size(); i++)
+                EXPECT_NO_THROW(nestedMap.AppendTextStringZAt(i + 1, STRING_VALUES[i].data()));
+
+            auto nestedArray = nestedMap.OpenArrayAt(4, INT64T_VALUES.size());
+            for (auto int64tValue : INT64T_VALUES)
+                EXPECT_NO_THROW(nestedArray.AppendInt64(int64tValue));
+        }
+
+        {
+            auto lastArray = array.OpenMap(INT64T_VALUES.size());
+            for (size_t i = 0; i < INT64T_VALUES.size(); i++)
+                EXPECT_NO_THROW(lastArray.AppendInt64At(i + 1, INT64T_VALUES[i]));
+        }
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserArray = parser.EnterArray();
+
+    for (auto x : INT64T_VALUES)
+        EXPECT_EQ(parserArray.GetInt64(), x);
+
+    {
+        auto firstMapParser = parserArray.EnterMap();
+        EXPECT_EQ(firstMapParser.GetTextStringAt(1), STRING_VALUES[0]);
+        EXPECT_EQ(firstMapParser.GetTextStringAt(2), STRING_VALUES[1]);
+        EXPECT_EQ(firstMapParser.GetTextStringAt(3), STRING_VALUES[2]);
+
+        auto nestedArrayParser = firstMapParser.EnterArrayAt(4).value();
+        for (auto x : INT64T_VALUES)
+            EXPECT_EQ(nestedArrayParser.GetInt64(), x);
+    }
+
+    {
+        auto secondMapParser = parserArray.EnterMap();
+        EXPECT_EQ(secondMapParser.GetInt64At(1), INT64T_VALUES[0]);
+        EXPECT_EQ(secondMapParser.GetInt64At(2), INT64T_VALUES[1]);
+        EXPECT_EQ(secondMapParser.GetInt64At(3), INT64T_VALUES[2]);
+        EXPECT_EQ(secondMapParser.GetInt64At(4), INT64T_VALUES[3]);
+    }
+}
+
+TEST(Cbor, DifferentTypesInArrayEncodingAndDecoding)
+{
+    Buffer buffer(12);
+    const std::vector<int64_t> INT64T_VALUES = {17, 22};
+    static constexpr std::string_view STRING_VALUE = "testing";
+    static constexpr bool BOOL_VALUE = false;
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto array = encoder.OpenArray(4);
+        EXPECT_NO_THROW(array.AppendInt64(INT64T_VALUES[0]));
+        EXPECT_NO_THROW(array.AppendTextString(STRING_VALUE.data()));
+        EXPECT_NO_THROW(array.AppendBoolean(BOOL_VALUE));
+        EXPECT_NO_THROW(array.AppendInt64(INT64T_VALUES[1]));
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserArray = parser.EnterArray();
+
+    EXPECT_EQ(parserArray.GetInt64(), INT64T_VALUES[0]);
+    EXPECT_EQ(parserArray.GetTextString(), STRING_VALUE);
+    EXPECT_EQ(parserArray.GetBoolean(), BOOL_VALUE);
+    EXPECT_EQ(parserArray.GetInt64(), INT64T_VALUES[1]);
+}
+
+TEST(Cbor, SkippingUndecodedEntriesUponContainerClose)
+{
+    Buffer buffer(62);
+    const Buffer BYTE_STRING = {0x063};
+    const std::vector<int64_t> INT64T_VALUES = {94, 38};
+    const std::vector<std::string_view> STRING_VALUES = {"restless", "agitated"};
+    auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());
+    {
+        auto map = encoder.OpenMap(5);
+        map.AppendInt64At(1, INT64T_VALUES[0]);
+        {
+            auto nestedMap = map.OpenMapAt(2, 3);
+            EXPECT_NO_THROW(nestedMap.AppendInt64At(1, INT64T_VALUES[1]));
+            EXPECT_NO_THROW(nestedMap.AppendTextStringZAt(2, STRING_VALUES[0].data()));
+            EXPECT_NO_THROW(nestedMap.AppendByteStringAt(3, BYTE_STRING));
+        }
+
+        map.AppendTextStringZAt(3, STRING_VALUES[1].data());
+        {
+            auto array = map.OpenArrayAt(4, 3);
+            array.AppendInt64(INT64T_VALUES[0]);
+            {
+                auto nestedArray = array.OpenArray(3);
+                EXPECT_NO_THROW(nestedArray.AppendInt64(INT64T_VALUES[1]));
+                EXPECT_NO_THROW(nestedArray.AppendTextStringZ(STRING_VALUES[0].data()));
+                EXPECT_NO_THROW(nestedArray.AppendByteString(BYTE_STRING));
+            }
+
+            array.AppendTextStringZ(STRING_VALUES[1].data());
+        }
+
+        map.AppendInt64At(5, INT64T_VALUES[1]);
+    }
+
+    EXPECT_EQ(encoder.GetBufferSize(), buffer.size());
+
+    auto parser = CborParsing::Parser::Create(buffer.data(), buffer.size());
+    auto parserMap = parser.EnterMap();
+
+    {
+        auto nestedMapParser = parserMap.EnterMapAt(2);
+        EXPECT_EQ(nestedMapParser.value().GetInt64At(1), INT64T_VALUES[1]);
+    }
+
+    EXPECT_EQ(parserMap.GetTextStringAt(3), STRING_VALUES[1]);
+
+    {
+        auto parserArray = parserMap.EnterArrayAt(4);
+        EXPECT_EQ(parserArray.value().GetInt64(), INT64T_VALUES[0]);
+
+        auto nestedArrayParser = parserArray.value().EnterArray();
+        EXPECT_EQ(nestedArrayParser.GetInt64(), INT64T_VALUES[1]);
+    }
+
+    EXPECT_EQ(parserMap.GetInt64At(5), INT64T_VALUES[1]);
+}
+
+#define TEST_CBOR_ENCODING(name, expectedValue, containerType, appendStatement)                   \
+    TEST(CborEncoding, name)                                                                      \
+    {                                                                                             \
+        static constexpr char rawData[] = expectedValue;                                          \
+        static constexpr auto expectedData = std::string_view{rawData, sizeof(rawData) - 1};      \
+        Buffer buffer(expectedData.size());                                                       \
+        auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());               \
+        {                                                                                         \
+            containerType;                                                                        \
+            appendStatement;                                                                      \
+        }                                                                                         \
+        EXPECT_EQ(encoder.GetBufferSize(), expectedData.size());                                  \
+        EXPECT_EQ(std::string_view(reinterpret_cast<const char *>(buffer.data()), buffer.size()), \
+                  expectedData);                                                                  \
+    }
+
+#define TEST_CBOR_ENCODING_TOO_SHORT_BUFFER(name, expectedSize, containerType, appendStatement) \
+    TEST(CborEncoding, name)                                                                    \
+    {                                                                                           \
+        Buffer buffer(expectedSize);                                                            \
+        auto encoder = CborEncoding::Encoder::Create(buffer.data(), buffer.size());             \
+        {                                                                                       \
+            containerType;                                                                      \
+            appendStatement;                                                                    \
+        }                                                                                       \
+    }
+
+#define TEST_CBOR_PARSING(name, expectedValue, containerType, assertStatement)                    \
+    TEST(CborParsing, name)                                                                       \
+    {                                                                                             \
+        static constexpr auto data = std::string_view{expectedValue};                             \
+        auto parser = CborParsing::Parser::Create(reinterpret_cast<const uint8_t *>(data.data()), \
+                                                  data.size());                                   \
+        containerType;                                                                            \
+        assertStatement;                                                                          \
+    }
+
+#define TEST_CBOR_PARSING_PREMATURE_END(name, expectedValue, parserStatement) \
+    TEST(CborParsing, name)                                                   \
+    {                                                                         \
+        static constexpr auto data = std::string_view{expectedValue};         \
+        parserStatement;                                                      \
+    }
+
+// AppendTextStringZ tests
+TEST_CBOR_ENCODING(ContainerNullInAppendTextStringZ,
+                   "\x81",
+                   auto array = encoder.OpenArray(1),
+                   ASSERT_THROW(array.AppendTextStringZ(nullptr), Unknown))
+TEST_CBOR_ENCODING(ContainerEmptyStringInAppendTextStringZ,
+                   "\x81\x60",
+                   auto array = encoder.OpenArray(1),
+                   array.AppendTextStringZ(""))
+TEST_CBOR_ENCODING(ContainerStringInAppendTextStringZ,
+                   "\x81\x64\x74\x65\x78\x74",
+                   auto array = encoder.OpenArray(1),
+                   array.AppendTextStringZ("text"))
+TEST_CBOR_ENCODING(ContainerEmptyStringInAppendTextString,
+                   "\x81\x60",
+                   auto array = encoder.OpenArray(1),
+                   array.AppendTextString(""))
+TEST_CBOR_ENCODING(ContainerStringInAppendTextString,
+                   "\x81\x64\x74\x65\x78\x74",
+                   auto array = encoder.OpenArray(1),
+                   array.AppendTextString("text"))
+
+// AppendInt64 tests
+TEST_CBOR_ENCODING(ContainerMinInt64ValueInAppendInt64,
+                   "\x81\x3B\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
+                   auto array = encoder.OpenArray(1),
+                   array.AppendInt64(std::numeric_limits<int64_t>::min()))
+TEST_CBOR_ENCODING(ContainerMaxInt64ValueInAppendInt64,
+                   "\x81\x1B\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
+                   auto array = encoder.OpenArray(1),
+                   array.AppendInt64(std::numeric_limits<int64_t>::max()))
+TEST_CBOR_ENCODING(ContainerNegativeValueInAppendInt64,
+                   "\x81\x20",
+                   auto array = encoder.OpenArray(1),
+                   array.AppendInt64(-1))
+TEST_CBOR_ENCODING(ContainerZeroValueInAppendInt64,
+                   "\x81\x00",
+                   auto array = encoder.OpenArray(1),
+                   array.AppendInt64(0))
+
+// AppendByteString tests
+const unsigned char wauthnChars[] = {0x83, 0x03, 0x6B};
+wauthn_const_buffer_s wauthnConstBuffer = {wauthnChars, sizeof(wauthnChars)};
+
+TEST_CBOR_ENCODING(ContainerEmptyStringInBufferTypeAppendByteString,
+                   "\x81\x40",
+                   auto array = encoder.OpenArray(1),
+                   array.AppendByteString(Buffer{}))
+TEST_CBOR_ENCODING(ContainerByteValueInBufferTypeAppendByteString,
+                   "\x81\x43\x83\x03\x6B",
+                   auto array = encoder.OpenArray(1),
+                   array.AppendByteString(Buffer{0x83, 0x03, 0x6B}))
+TEST_CBOR_ENCODING(ContainerEmptyStringInWauthnBufferTypeAppendByteString,
+                   "\x81\x40",
+                   auto array = encoder.OpenArray(1),
+                   array.AppendByteString(wauthn_const_buffer_s{}))
+TEST_CBOR_ENCODING(ContainerByteValueInWauthnBufferTypeAppendByteString,
+                   "\x81\x43\x83\x03\x6B",
+                   auto array = encoder.OpenArray(1),
+                   array.AppendByteString(wauthnConstBuffer))
+
+// AppendBoolean tests
+TEST_CBOR_ENCODING(ContainerByteValueInAppendBooleanFalse,
+                   "\x81\xF4",
+                   auto array = encoder.OpenArray(1),
+                   array.AppendBoolean(false))
+TEST_CBOR_ENCODING(ContainerByteValueInAppendBooleanTrue,
+                   "\x81\xF5",
+                   auto array = encoder.OpenArray(1),
+                   array.AppendBoolean(true))
+
+// AppendByteStringAt(const Buffer&) tests
+TEST_CBOR_ENCODING(SortedMapIntKeyInAppendByteStringAtOfBuffer,
+                   "\xa1\x07\x43\x83\x03\x6B",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendByteStringAt(7, Buffer{0x83, 0x03, 0x6B}))
+TEST_CBOR_ENCODING(SortedMapCStrKeyInAppendByteStringAtOfBuffer,
+                   "\xa1\x63\x61\x62\x63\x43\x83\x03\x6B",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendByteStringAt("abc", Buffer{0x83, 0x03, 0x6B}))
+TEST_CBOR_ENCODING(SortedMapEmptyCStrKeyInAppendByteStringAtOfBuffer,
+                   "\xa1\x60\x43\x83\x03\x6B",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendByteStringAt("", Buffer{0x83, 0x03, 0x6B}))
+TEST_CBOR_ENCODING(SortedMapEmptyValueInAppendByteStringAtOfBuffer,
+                   "\xa1\x63\x61\x62\x63\x40",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendByteStringAt("abc", Buffer{}))
+TEST_CBOR_ENCODING(SortedMapStringKeyInAppendByteStringAtOfBuffer,
+                   "\xa1\x63\x61\x62\x63\x43\x83\x03\x6B",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendByteStringAt(std::string_view{"abc"}, Buffer{0x83, 0x03, 0x6B}))
+TEST_CBOR_ENCODING(SortedMapEmptyStringKeyInAppendByteStringAtOfBuffer,
+                   "\xa1\x60\x43\x83\x03\x6B",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendByteStringAt(std::string_view{""}, Buffer{0x83, 0x03, 0x6B}))
+TEST_CBOR_ENCODING(SortedMapNullKeyInAppendByteStringAtOfBuffer,
+                   "\xa1",
+                   auto map = encoder.OpenMap(1),
+                   EXPECT_THROW(map.AppendByteStringAt(nullptr, Buffer{0x03}), Unknown))
+
+// AppendByteStringAt(const wauthn_const_buffer&) tests
+TEST_CBOR_ENCODING(SortedMapIntKeyInAppendByteStringAtOfWauthnBuffer,
+                   "\xa1\x07\x43\x83\x03\x6B",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendByteStringAt(7, wauthnConstBuffer))
+TEST_CBOR_ENCODING(SortedMapCStrKeyInAppendByteStringAtOfWauthnBuffer,
+                   "\xa1\x63\x61\x62\x63\x43\x83\x03\x6B",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendByteStringAt("abc", wauthnConstBuffer))
+TEST_CBOR_ENCODING(SortedMapEmptyCStrKeyInAppendByteStringAtOfWauthnBuffer,
+                   "\xa1\x60\x43\x83\x03\x6B",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendByteStringAt("", wauthnConstBuffer))
+TEST_CBOR_ENCODING(SortedMapEmptyValueInAppendByteStringAtOfWauthnBuffer,
+                   "\xa1\x63\x61\x62\x63\x40",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendByteStringAt("abc", wauthn_const_buffer_s{}))
+TEST_CBOR_ENCODING(SortedMapStringKeyInAppendByteStringAtOfWauthnBuffer,
+                   "\xa1\x63\x61\x62\x63\x43\x83\x03\x6B",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendByteStringAt(std::string_view{"abc"}, wauthnConstBuffer))
+TEST_CBOR_ENCODING(SortedMapEmptyStringKeyAppendByteStringAtOfWauthnBuffer,
+                   "\xa1\x60\x43\x83\x03\x6B",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendByteStringAt(std::string_view{""}, wauthnConstBuffer))
+TEST_CBOR_ENCODING(SortedMapNullKeyInAppendByteStringAtOfWauthnBuffer,
+                   "\xa1",
+                   auto map = encoder.OpenMap(1),
+                   EXPECT_THROW(map.AppendByteStringAt(nullptr, wauthnConstBuffer), Unknown))
+
+// AppendTextStringZAt tests
+TEST_CBOR_ENCODING(SortedMapIntKeyInAppendTextStringZAt,
+                   "\xa1\x07\x63\x61\x62\x63",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendTextStringZAt(7, "abc"))
+TEST_CBOR_ENCODING(SortedMapCStrKeyInAppendTextStringZAt,
+                   "\xa1\x63\x61\x62\x63\x63\x78\x79\x7A",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendTextStringZAt("abc", "xyz"))
+TEST_CBOR_ENCODING(SortedMapEmptyCStrKeyInAppendTextStringZAt,
+                   "\xa1\x60\x63\x78\x79\x7A",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendTextStringZAt("", "xyz"))
+TEST_CBOR_ENCODING(SortedMapEmptyStringValueInAppendTextStringZAt,
+                   "\xa1\x63\x61\x62\x63\x60",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendTextStringZAt("abc", ""))
+TEST_CBOR_ENCODING(SortedMapNullStringValueInAppendTextStringZAt,
+                   "\xa1",
+                   auto map = encoder.OpenMap(1),
+                   EXPECT_THROW(map.AppendTextStringZAt("abc", nullptr), Unknown))
+TEST_CBOR_ENCODING(SortedMapStringKeyInAppendTextStringZAt,
+                   "\xa1\x63\x61\x62\x63\x63\x61\x62\x63",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendTextStringZAt(std::string_view{"abc"}, "abc"))
+TEST_CBOR_ENCODING(SortedMapEmptyStringKeyInAppendTextStringZAt,
+                   "\xa1\x60\x63\x61\x62\x63",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendTextStringZAt(std::string_view{""}, "abc"))
+TEST_CBOR_ENCODING(SortedMapNullKeyInAppendAppendTextStringZAt,
+                   "\xa1",
+                   auto map = encoder.OpenMap(1),
+                   EXPECT_THROW(map.AppendTextStringZAt(nullptr, "abc"), Unknown))
+
+// AppendOptionalTextStringZAt tests
+TEST_CBOR_ENCODING(SortedMapIntKeyInAppendOptionalTextStringZAt,
+                   "\xa1\x07\x63\x61\x62\x63",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendOptionalTextStringZAt(7, "abc"))
+TEST_CBOR_ENCODING(SortedMapCStrKeyInAppendOptionalTextStringZAt,
+                   "\xa1\x63\x61\x62\x63\x63\x78\x79\x7A",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendOptionalTextStringZAt("abc", "xyz"))
+TEST_CBOR_ENCODING(SortedMapEmptyCStrKeyInAppendOptionalTextStringZAt,
+                   "\xa1\x60\x63\x78\x79\x7A",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendOptionalTextStringZAt("", "xyz"))
+TEST_CBOR_ENCODING(SortedMapEmptyStringValueInAppendOptionalTextStringZAt,
+                   "\xa1\x63\x61\x62\x63\x60",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendOptionalTextStringZAt("abc", ""))
+TEST_CBOR_ENCODING(SortedMapNullStringValueInAppendOptionalTextStringZAt,
+                   "\xa1",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendOptionalTextStringZAt("abc", nullptr))
+TEST_CBOR_ENCODING(SortedMapStringKeyInAppendOptionalTextStringZAt,
+                   "\xa1\x63\x61\x62\x63\x63\x78\x79\x7A",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendOptionalTextStringZAt(std::string_view{"abc"}, "xyz"))
+TEST_CBOR_ENCODING(SortedMapEmptyStringKeyInAppendOptionalTextStringZAt,
+                   "\xa1\x60\x63\x78\x79\x7A",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendOptionalTextStringZAt(std::string_view{""}, "xyz"))
+TEST_CBOR_ENCODING(SortedMapNullKeyInAppendOptionalTextStringZAt,
+                   "\xa1",
+                   auto map = encoder.OpenMap(1),
+                   EXPECT_THROW(map.AppendOptionalTextStringZAt(nullptr, "abc"), Unknown))
+
+// AppendInt64At tests
+TEST_CBOR_ENCODING(SortedMapIntKeyInAppendInt64At,
+                   "\xa1\x07\x07",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendInt64At(7, 7))
+TEST_CBOR_ENCODING(SortedMapCStrKeyInAppendInt64At,
+                   "\xa1\x63\x61\x62\x63\x07",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendInt64At("abc", 7))
+TEST_CBOR_ENCODING(SortedMapEmptyCStrKeyInAppendInt64At,
+                   "\xa1\x60\x07",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendInt64At("", 7))
+TEST_CBOR_ENCODING(SortedMapMinInt64ValueInAppendInt64At,
+                   "\xa1\x07\x3B\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendInt64At(7, std::numeric_limits<int64_t>::min()))
+TEST_CBOR_ENCODING(SortedMapMaxInt64ValueInAppendInt64At,
+                   "\xa1\x07\x1B\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendInt64At(7, std::numeric_limits<int64_t>::max()))
+TEST_CBOR_ENCODING(SortedMapZeroValueInAppendInt64At,
+                   "\xa1\x02\x00",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendInt64At(2, 0))
+TEST_CBOR_ENCODING(SortedMapStringKeyInAppendInt64At,
+                   "\xa1\x63\x61\x62\x63\x07",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendInt64At(std::string_view{"abc"}, 7))
+TEST_CBOR_ENCODING(SortedMapEmptyStringKeyInAppendInt64At,
+                   "\xa1\x60\x07",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendInt64At(std::string_view{""}, 7))
+TEST_CBOR_ENCODING(SortedMapNullKeyInAppendInt64At,
+                   "\xa1",
+                   auto map = encoder.OpenMap(1),
+                   EXPECT_THROW(map.AppendInt64At(nullptr, 7), Unknown))
+
+// AppendBooleanAt tests
+TEST_CBOR_ENCODING(SortedMapIntKeyInAppendBooleanAt,
+                   "\xa1\x07\xF5",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendBooleanAt(7, true))
+TEST_CBOR_ENCODING(SortedMapCStrKeyInAppendBooleanAt,
+                   "\xa1\x63\x61\x62\x63\xF5",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendBooleanAt("abc", true))
+TEST_CBOR_ENCODING(SortedMapEmptyCStrKeyInAppendBooleanAt,
+                   "\xa1\x60\xF5",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendBooleanAt("", true))
+TEST_CBOR_ENCODING(SortedMapTrueValueInAppendBooleanAt,
+                   "\xa1\x07\xF5",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendBooleanAt(7, true))
+TEST_CBOR_ENCODING(SortedMapFalseValueInAppendBooleanAt,
+                   "\xa1\x02\xF4",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendBooleanAt(2, false))
+TEST_CBOR_ENCODING(SortedMapStringKeyInAppendBooleanAt,
+                   "\xa1\x63\x61\x62\x63\xF5",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendBooleanAt(std::string_view{"abc"}, true))
+TEST_CBOR_ENCODING(SortedMapEmptyStringKeyInAppendBooleanAt,
+                   "\xa1\x60\xF5",
+                   auto map = encoder.OpenMap(1),
+                   map.AppendBooleanAt(std::string_view{""}, true))
+TEST_CBOR_ENCODING(SortedMapNullKeyInAppendBooleanAt,
+                   "\xa1",
+                   auto map = encoder.OpenMap(1),
+                   EXPECT_THROW(map.AppendBooleanAt(nullptr, true), Unknown))
+
+// Too short buffer array encoding tests
+TEST_CBOR_ENCODING_TOO_SHORT_BUFFER(TooShortBufferInContainerAppendTextStringZ,
+                                    2 - 1,
+                                    auto array = encoder.OpenArray(1),
+                                    EXPECT_THROW(array.AppendTextStringZ(""), EncodingFailed))
+TEST_CBOR_ENCODING_TOO_SHORT_BUFFER(TooShortBufferInContainerAppendTextString,
+                                    2 - 1,
+                                    auto array = encoder.OpenArray(1),
+                                    EXPECT_THROW(array.AppendTextString(""), EncodingFailed))
+TEST_CBOR_ENCODING_TOO_SHORT_BUFFER(TooShortBufferInContainerAppendInt64,
+                                    2 - 1,
+                                    auto array = encoder.OpenArray(1),
+                                    EXPECT_THROW(array.AppendInt64(0), EncodingFailed))
+TEST_CBOR_ENCODING_TOO_SHORT_BUFFER(TooShortBufferInContainerAppendByteStringOfBuffer,
+                                    2 - 1,
+                                    auto array = encoder.OpenArray(1),
+                                    EXPECT_THROW(array.AppendByteString(Buffer{}), EncodingFailed))
+TEST_CBOR_ENCODING_TOO_SHORT_BUFFER(TooShortBufferInContainerAppendBoolean,
+                                    2 - 1,
+                                    auto array = encoder.OpenArray(1),
+                                    EXPECT_THROW(array.AppendBoolean(true), EncodingFailed))
+TEST_CBOR_ENCODING_TOO_SHORT_BUFFER(TooShortBufferInContainerAppendByteStringOfWauthnBuffer,
+                                    2 - 1,
+                                    auto array = encoder.OpenArray(1),
+                                    EXPECT_THROW(array.AppendByteString(wauthn_const_buffer_s{}),
+                                                 EncodingFailed))
+
+// Too short buffer map encoding tests
+TEST_CBOR_ENCODING_TOO_SHORT_BUFFER(TooShortBufferInSortedMapAppendByteStringAtOfBuffer,
+                                    3 - 1,
+                                    auto map = encoder.OpenMap(1),
+                                    EXPECT_THROW(map.AppendByteStringAt("", Buffer{}),
+                                                 EncodingFailed))
+TEST_CBOR_ENCODING_TOO_SHORT_BUFFER(TooShortBufferInSortedMapAppendTextStringZAt,
+                                    3 - 1,
+                                    auto map = encoder.OpenMap(1),
+                                    EXPECT_THROW(map.AppendTextStringZAt("", ""), EncodingFailed))
+TEST_CBOR_ENCODING_TOO_SHORT_BUFFER(TooShortBufferInSortedMapAppendOptionalTextStringZAt,
+                                    3 - 1,
+                                    auto map = encoder.OpenMap(1),
+                                    EXPECT_THROW(map.AppendOptionalTextStringZAt("", ""),
+                                                 EncodingFailed))
+TEST_CBOR_ENCODING_TOO_SHORT_BUFFER(TooShortBufferInSortedMapAppendInt64At,
+                                    3 - 1,
+                                    auto map = encoder.OpenMap(1),
+                                    EXPECT_THROW(map.AppendInt64At(0, 0), EncodingFailed))
+TEST_CBOR_ENCODING_TOO_SHORT_BUFFER(TooShortBufferInSortedMapAppendBooleanAt,
+                                    3 - 1,
+                                    auto map = encoder.OpenMap(1),
+                                    {
+                                        EXPECT_THROW(map.AppendBooleanAt(0, false), EncodingFailed);
+                                    })
+TEST_CBOR_ENCODING_TOO_SHORT_BUFFER(
+    TooShortBufferInSortedMapAppendByteStringAtOfWauthnBuffer,
+    3 - 1,
+    auto map = encoder.OpenMap(1),
+    EXPECT_THROW(map.AppendByteStringAt("", wauthn_const_buffer_s{}), EncodingFailed))
+
+// Parser premature end test
+TEST_CBOR_PARSING_PREMATURE_END(ContainerArrayEndedPrematurely, "\x81\x61", {
+    EXPECT_THROW(
+        CborParsing::Parser::Create(reinterpret_cast<const uint8_t *>(data.data()), data.size()),
+        Unknown);
+})
+TEST_CBOR_PARSING_PREMATURE_END(SortedMapMapEndedPrematurely, "\xa1\x61", {
+    EXPECT_THROW(
+        CborParsing::Parser::Create(reinterpret_cast<const uint8_t *>(data.data()), data.size()),
+        Unknown);
+})
+
+// GetInt64 tests
+TEST_CBOR_PARSING(ContainerCorrectValueInGetInt64,
+                  "\x81\x11",
+                  auto container = parser.EnterArray(),
+                  EXPECT_EQ(container.GetInt64(), 17))
+TEST_CBOR_PARSING(ContainerNullValueInGetInt64,
+                  "\x81\xF6",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetInt64(), Unknown))
+TEST_CBOR_PARSING(ContainerUndefinedValueInGetInt64,
+                  "\x81\xF7",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetInt64(), Unknown))
+TEST_CBOR_PARSING(ContainerDifferentTypeValueInGetInt64,
+                  "\x81\x40",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetInt64(), Unknown))
+TEST_CBOR_PARSING(ContainerArrayEndedInGetInt64,
+                  "\x80",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetInt64(), Unknown))
+
+// GetTextString tests
+TEST_CBOR_PARSING(ContainerEmptyValueInGetTextString,
+                  "\x81\x60",
+                  auto container = parser.EnterArray(),
+                  EXPECT_EQ(container.GetTextString(), ""))
+TEST_CBOR_PARSING(ContainerCorrectValueInGetTextString,
+                  "\x81\x64\x74\x65\x73\x74",
+                  auto container = parser.EnterArray(),
+                  EXPECT_EQ(container.GetTextString(), "test"))
+TEST_CBOR_PARSING(ContainerNullValueInGetTextString,
+                  "\x81\xF6",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetTextString(), Unknown))
+TEST_CBOR_PARSING(ContainerUndefinedValueInGetTextString,
+                  "\x81\xF7",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetTextString(), Unknown))
+TEST_CBOR_PARSING(ContainerDifferentTypeValueInGetTextString,
+                  "\x81\x40",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetTextString(), Unknown))
+TEST_CBOR_PARSING(ContainerArrayEndedInGetTextString,
+                  "\x80",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetTextString(), Unknown))
+
+// GetByteString tests
+TEST_CBOR_PARSING(ContainerEmptyValueInGetByteString,
+                  "\x81\x40",
+                  auto container = parser.EnterArray(),
+                  EXPECT_EQ(container.GetByteString(), Buffer{}))
+TEST_CBOR_PARSING(ContainerCorrectValueInGetByteString,
+                  "\x81\x41\x83",
+                  auto container = parser.EnterArray(),
+                  EXPECT_EQ(container.GetByteString(), Buffer{0x83}))
+TEST_CBOR_PARSING(ContainerNullValueInGetByteString,
+                  "\x81\xF6",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetByteString(), Unknown))
+TEST_CBOR_PARSING(ContainerUndefinedValueInGetByteString,
+                  "\x81\xF7",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetByteString(), Unknown))
+TEST_CBOR_PARSING(ContainerDifferentTypeValueInGetByteString,
+                  "\x81\x60",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetByteString(), Unknown))
+TEST_CBOR_PARSING(ContainerArrayEndedInGetByteString,
+                  "\x80",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetByteString(), Unknown))
+
+// GetBoolean tests
+TEST_CBOR_PARSING(ContainerTrueValueInGetBoolean,
+                  "\x81\xF5",
+                  auto container = parser.EnterArray(),
+                  EXPECT_EQ(container.GetBoolean(), true))
+TEST_CBOR_PARSING(ContainerFalseValueInGetBoolean,
+                  "\x81\xF4",
+                  auto container = parser.EnterArray(),
+                  EXPECT_EQ(container.GetBoolean(), false))
+TEST_CBOR_PARSING(ContainerNullValueInGetBoolean,
+                  "\x81\xF6",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetBoolean(), Unknown))
+TEST_CBOR_PARSING(ContainerUndefinedValueInGetBoolean,
+                  "\x81\xF7",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetBoolean(), Unknown))
+TEST_CBOR_PARSING(ContainerDifferentTypeValueInGetBoolean,
+                  "\x81\x40",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetBoolean(), Unknown))
+TEST_CBOR_PARSING(ContainerArrayEndedInGetBoolean,
+                  "\x80",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetBoolean(), Unknown))
+
+// GetUint64 tests
+TEST_CBOR_PARSING(ContainerCorrectValueInGetUint64,
+                  "\x81\x10",
+                  auto container = parser.EnterArray(),
+                  EXPECT_EQ(container.GetUint64(), 16))
+TEST_CBOR_PARSING(ContainerNegativeValueInGetUint64,
+                  "\x81\x20",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetUint64(), Unknown))
+TEST_CBOR_PARSING(ContainerNullValueInGetUint64,
+                  "\x81\xF6",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetUint64(), Unknown))
+TEST_CBOR_PARSING(ContainerUndefinedValueInGetUint64,
+                  "\x81\xF7",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetUint64(), Unknown))
+TEST_CBOR_PARSING(ContainerDifferentTypeValueInGetUint64,
+                  "\x81\x40",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetUint64(), Unknown))
+TEST_CBOR_PARSING(ContainerArrayEndedInGetUint64,
+                  "\x80",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetUint64(), Unknown))
+
+// EnterMap tests
+TEST_CBOR_PARSING(ContainerCorrectValueInEnterMap,
+                  "\xA1\x01\x10",
+                  auto container = parser.EnterMap(),
+                  EXPECT_EQ(container.GetUint64At(1), 16))
+TEST_CBOR_PARSING(ContainerEmptyMapInEnterMap,
+                  "\xA0",
+                  auto container = parser.EnterMap(),
+                  EXPECT_EQ(container.GetUint64At(0), std::nullopt))
+TEST_CBOR_PARSING(ContainerNullValueInEnterMap,
+                  "\xF6",
+                  EXPECT_THROW(parser.EnterMap(), Unknown),
+                  {})
+TEST_CBOR_PARSING(ContainerUndefinedValueInEnterMap,
+                  "\xF7",
+                  EXPECT_THROW(parser.EnterMap(), Unknown),
+                  {})
+TEST_CBOR_PARSING(ContainerDifferentTypeValueInEnterMap,
+                  "\x40",
+                  EXPECT_THROW(parser.EnterMap(), Unknown),
+                  {})
+TEST_CBOR_PARSING(ContainerArrayInEnterMap,
+                  "\x81\x01",
+                  EXPECT_THROW(parser.EnterMap(), Unknown),
+                  {})
+
+// EnterArray tests
+TEST_CBOR_PARSING(ContainerCorrectValueInEnterArray,
+                  "\x81\x10",
+                  auto container = parser.EnterArray(),
+                  EXPECT_EQ(container.GetUint64(), 16))
+TEST_CBOR_PARSING(ContainerEmptyArrayInEnterArray,
+                  "\x80",
+                  auto container = parser.EnterArray(),
+                  EXPECT_THROW(container.GetUint64(), Unknown))
+TEST_CBOR_PARSING(ContainerNullValueInEnterArray,
+                  "\xF6",
+                  EXPECT_THROW(parser.EnterArray(), Unknown),
+                  {})
+TEST_CBOR_PARSING(ContainerUndefinedValueInEnterArray,
+                  "\xF7",
+                  EXPECT_THROW(parser.EnterArray(), Unknown),
+                  {})
+TEST_CBOR_PARSING(ContainerDifferentTypeValueInEnterArray,
+                  "\x40",
+                  EXPECT_THROW(parser.EnterArray(), Unknown),
+                  {})
+TEST_CBOR_PARSING(ContainerMapInEnterArray,
+                  "\xA1\x01\x01",
+                  EXPECT_THROW(parser.EnterArray(), Unknown),
+                  {})
+
+// EnterArrayAt tests
+TEST_CBOR_PARSING(SortedMapNullKeyInEnterArrayAt,
+                  "\xa1\xF6\x81\x63\x61\x62\x63",
+                  EXPECT_THROW(parser.EnterMap().EnterArrayAt(nullptr), Unknown),
+                  {})
+TEST_CBOR_PARSING(SortedMapUndefinedKeyInEnterArrayAt,
+                  "\xa1\xF7\x81\x63\x61\x62\x63",
+                  EXPECT_THROW(parser.EnterMap().EnterArrayAt(CborParsing::CURRENT_KEY), Unknown),
+                  {})
+TEST_CBOR_PARSING(SortedMapNullValueInEnterArrayAt,
+                  "\xa1\x07\xF6",
+                  EXPECT_THROW(parser.EnterMap().EnterArrayAt(7), Unknown),
+                  {})
+TEST_CBOR_PARSING(SortedMapUndefinedValueInEnterArrayAt,
+                  "\xa1\x07\xF7",
+                  auto outerMap = parser.EnterMap();
+                  EXPECT_THROW(auto map = outerMap.EnterArrayAt(7), Unknown), {})
+TEST_CBOR_PARSING(SortedMapEmptyMapInEnterArrayAt,
+                  "\xa1\x07\xa0",
+                  EXPECT_THROW(parser.EnterMap().EnterArrayAt(7), Unknown),
+                  {})
+TEST_CBOR_PARSING(SortedMapValueOfDifferentTypeInEnterArrayAt,
+                  "\xa1\x07\x40",
+                  EXPECT_THROW(parser.EnterMap().EnterArrayAt(7), Unknown),
+                  {})
+TEST_CBOR_PARSING(SortedMapMapInEnterArrayAt,
+                  "\xa1\x07\xa1\x01\x07",
+                  EXPECT_THROW(parser.EnterMap().EnterArrayAt(7), Unknown),
+                  {})
+TEST_CBOR_PARSING(SortedMapEmptyArrayInEnterArrayAt,
+                  "\xa1\x07\x80",
+                  auto outerMap = parser.EnterMap();
+                  auto map = outerMap.EnterArrayAt(7).value(),
+                  EXPECT_THROW(map.GetInt64(), Unknown))
+TEST_CBOR_PARSING(SortedMapNonEmptyArrayInEnterArrayAt,
+                  "\xa1\x07\x81\x07",
+                  auto outerMap = parser.EnterMap();
+                  auto map = outerMap.EnterArrayAt(7).value(), EXPECT_EQ(map.GetInt64(), 7))
+TEST_CBOR_PARSING(SortedMapCurrentKeyNullKeyInEnterArrayAt,
+                  "\xa1\xF6\x81\x07",
+                  auto outerMap = parser.EnterMap();
+                  EXPECT_THROW(outerMap.EnterArrayAt(CborParsing::CURRENT_KEY), Unknown), {})
+TEST_CBOR_PARSING(SortedMapCurrentKeyUndefinedKeyInEnterArrayAt,
+                  "\xa1\xF7\x81\x07",
+                  auto outerMap = parser.EnterMap();
+                  EXPECT_THROW(outerMap.EnterArrayAt(CborParsing::CURRENT_KEY), Unknown), {})
+
+// EnterMapAt tests
+TEST_CBOR_PARSING(SortedMapNullKeyInEnterMapAt,
+                  "\xa1\xF6\xa1\x02\x63\x61\x62\x63",
+                  EXPECT_THROW(parser.EnterMap().EnterMapAt(nullptr), Unknown),
+                  {})
+TEST_CBOR_PARSING(SortedMapUndefinedKeyInEnterMapAt,
+                  "\xa1\xF7\xa1\x02\x63\x61\x62\x63",
+                  EXPECT_THROW(parser.EnterMap().EnterMapAt(CborParsing::CURRENT_KEY), Unknown),
+                  {})
+TEST_CBOR_PARSING(SortedMapNullValueInEnterMapAt,
+                  "\xa1\x07\xF6",
+                  EXPECT_THROW(parser.EnterMap().EnterMapAt(7), Unknown),
+                  {})
+TEST_CBOR_PARSING(SortedMapUndefinedValueInEnterMapAt,
+                  "\xa1\x07\xF7",
+                  EXPECT_THROW(parser.EnterMap().EnterMapAt(7), Unknown),
+                  {})
+TEST_CBOR_PARSING(SortedMapEmptyArrayInEnterMapAt,
+                  "\xa1\x07\x80",
+                  auto outerMap = parser.EnterMap();
+                  EXPECT_THROW(outerMap.EnterMapAt(7), Unknown), {})
+TEST_CBOR_PARSING(SortedMapValueOfDifferentTypeInEnterMapAt,
+                  "\xa1\x07\x40",
+                  EXPECT_THROW(parser.EnterMap().EnterMapAt(7), Unknown),
+                  {})
+TEST_CBOR_PARSING(SortedMapArrayInEnterMapAt,
+                  "\xa1\x07\x81\x07",
+                  EXPECT_THROW(parser.EnterMap().EnterMapAt(7), Unknown),
+                  {})
+TEST_CBOR_PARSING(SortedMapEmptyMapInEnterMapAt, "\xa1\x07\xa0", auto outerMap = parser.EnterMap();
+                  auto map = outerMap.EnterMapAt(7).value(),
+                  EXPECT_EQ(map.GetInt64At(CborParsing::CURRENT_KEY), std::nullopt))
+TEST_CBOR_PARSING(SortedMapNonEmptyMapInEnterMapAt,
+                  "\xa1\x07\xa1\x01\x07",
+                  auto outerMap = parser.EnterMap();
+                  auto map = outerMap.EnterMapAt(7).value(), EXPECT_EQ(map.GetInt64At(1), 7))
+TEST_CBOR_PARSING(SortedMapCurrentKeyNullKeyInEnterMapAt,
+                  "\xa1\xF6\xa1\x01\x07",
+                  auto outerMap = parser.EnterMap();
+                  EXPECT_THROW(outerMap.EnterMapAt(CborParsing::CURRENT_KEY), Unknown), {})
+TEST_CBOR_PARSING(SortedMapCurrentKeyUndefinedKeyInEnterMapAt,
+                  "\xa1\xF7\xa1\x01\x07",
+                  auto outerMap = parser.EnterMap();
+                  EXPECT_THROW(outerMap.EnterMapAt(CborParsing::CURRENT_KEY), Unknown), {})
+
+// GetInt64At tests
+TEST_CBOR_PARSING(SortedMapIntKeyInGetInt64At,
+                  "\xa1\x07\07",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetInt64At(7), 7))
+TEST_CBOR_PARSING(SortedMapEmptyStringInGetInt64At,
+                  "\xa1\x60\x07",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetInt64At(""), 7))
+TEST_CBOR_PARSING(SortedMapCurrentIntKeyInGetInt64At,
+                  "\xa1\x07\x07",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetInt64At(CborParsing::CURRENT_KEY), 7))
+TEST_CBOR_PARSING(SortedMapCurrentStringKeyInGetInt64At,
+                  "\xa1\x63\x61\x62\x63\x07",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetInt64At(CborParsing::CURRENT_KEY), 7))
+TEST_CBOR_PARSING(SortedMapCurrentKeyInEmptyMapInGetInt64At,
+                  "\xa0",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetInt64At(CborParsing::CURRENT_KEY), std::nullopt))
+TEST_CBOR_PARSING(SortedMapNullValueInGetInt64At,
+                  "\xa1\x60\xF6",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(map.GetInt64At(CborParsing::CURRENT_KEY), Unknown))
+TEST_CBOR_PARSING(SortedMapUndefinedValueInGetInt64At,
+                  "\xa1\x60\xF7",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(map.GetInt64At(CborParsing::CURRENT_KEY), Unknown))
+TEST_CBOR_PARSING(SortedMapCurrentKeyAtEndOfMapInGetInt64At,
+                  "\xa1\x07\x07",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetInt64At(CborParsing::CURRENT_KEY), 7);
+                      EXPECT_EQ(map.GetInt64At(CborParsing::CURRENT_KEY), std::nullopt);
+                  })
+TEST_CBOR_PARSING(SortedMapNonexistentIntKeyInGetInt64At,
+                  "\xa1\x07\x07",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetInt64At(5), std::nullopt);
+                      EXPECT_EQ(map.GetInt64At(CborParsing::CURRENT_KEY), 7);
+                      EXPECT_EQ(map.GetInt64At(42), std::nullopt);
+                  })
+TEST_CBOR_PARSING(SortedMapNonexistentStringKeyInGetInt64At,
+                  "\xa1\x63\x61\x62\x63\x07",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetInt64At("xyz"), std::nullopt);
+                      EXPECT_EQ(map.GetInt64At(CborParsing::CURRENT_KEY), 7);
+                      EXPECT_EQ(map.GetInt64At("qwe"), std::nullopt);
+                  })
+TEST_CBOR_PARSING(SortedMapDifferentValueInGetInt64At,
+                  "\xa1\x60\x40",
+                  auto map = parser.EnterMap(),
+                  { EXPECT_THROW(map.GetInt64At(CborParsing::CURRENT_KEY), Unknown); })
+TEST_CBOR_PARSING(SortedMapNullKeyInGetInt64At, "\xa1\xF6\x07", auto map = parser.EnterMap(), {
+    EXPECT_EQ(map.GetInt64At(""), std::nullopt);
+    EXPECT_THROW(map.GetInt64At(CborParsing::CURRENT_KEY), Unknown);
+})
+TEST_CBOR_PARSING(SortedMapUndefinedKeyInGetInt64At, "\xa1\xF7\x07", auto map = parser.EnterMap(), {
+    EXPECT_EQ(map.GetInt64At(""), std::nullopt);
+    EXPECT_THROW(map.GetInt64At(CborParsing::CURRENT_KEY), Unknown);
+})
+
+// GetTextStringAt tests
+TEST_CBOR_PARSING(SortedMapCurrentIntKeyInGetTextStringAt,
+                  "\xa1\x07\x63\x61\x62\x63",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetTextStringAt(CborParsing::CURRENT_KEY), "abc"))
+TEST_CBOR_PARSING(SortedMapCurrentStringKeyInGetTextStringAt,
+                  "\xa1\x63\x61\x62\x63\x63\x78\x79\x7A",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetTextStringAt(CborParsing::CURRENT_KEY), "xyz"))
+TEST_CBOR_PARSING(SortedMapIntKeyInGetTextStringAt,
+                  "\xa1\x07\x63\x61\x62\x63",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetTextStringAt(7), "abc"))
+TEST_CBOR_PARSING(SortedMapEmptyStringInGetTextStringAt,
+                  "\xa1\x60\x63\x78\x79\x7a",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetTextStringAt(""), "xyz"))
+TEST_CBOR_PARSING(SortedMapCurrentKeyInEmptyMapInGetTextStringAt,
+                  "\xa0",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetTextStringAt(CborParsing::CURRENT_KEY), std::nullopt))
+TEST_CBOR_PARSING(SortedMapNullValueInGetTextStringAt,
+                  "\xa1\x60\xF6",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(map.GetTextStringAt(CborParsing::CURRENT_KEY), Unknown))
+TEST_CBOR_PARSING(SortedMapUndefinedValueInGetTextStringAt,
+                  "\xa1\x60\xF7",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(map.GetTextStringAt(CborParsing::CURRENT_KEY), Unknown))
+TEST_CBOR_PARSING(SortedMapDifferentValueInGetTextStringAt,
+                  "\xa1\x60\x40",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(map.GetTextStringAt(CborParsing::CURRENT_KEY), Unknown))
+TEST_CBOR_PARSING(SortedMapCurrentKeyAtEndOfMapInGetTextStringAt,
+                  "\xa1\x07\x60",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetTextStringAt(CborParsing::CURRENT_KEY), "");
+                      EXPECT_EQ(map.GetTextStringAt(CborParsing::CURRENT_KEY), std::nullopt);
+                  })
+TEST_CBOR_PARSING(SortedMapNonexistentIntKeyInGetTextStringAt,
+                  "\xa1\x07\x63\x61\x62\x63",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetTextStringAt(5), std::nullopt);
+                      EXPECT_EQ(map.GetTextStringAt(CborParsing::CURRENT_KEY), "abc");
+                      EXPECT_EQ(map.GetTextStringAt(42), std::nullopt);
+                  })
+TEST_CBOR_PARSING(SortedMapNonexistentStringKeyInGetTextStringAt,
+                  "\xa1\x63\x61\x62\x63\x63\x61\x62\x63",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetTextStringAt("xyz"), std::nullopt);
+                      EXPECT_EQ(map.GetTextStringAt(CborParsing::CURRENT_KEY), "abc");
+                      EXPECT_EQ(map.GetTextStringAt("qwe"), std::nullopt);
+                  })
+TEST_CBOR_PARSING(SortedMapNullKeyInGetTextStringAt,
+                  "\xa1\xF6\x63\x78\x79\x7A",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetTextStringAt(""), std::nullopt);
+                      EXPECT_THROW(map.GetTextStringAt(CborParsing::CURRENT_KEY), Unknown);
+                  })
+TEST_CBOR_PARSING(SortedMapUndefinedKeyInGetTextStringAt,
+                  "\xa1\xF7\x63\x61\x62\x63",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetTextStringAt(""), std::nullopt);
+                      EXPECT_THROW(map.GetTextStringAt(CborParsing::CURRENT_KEY), Unknown);
+                  })
+
+// GetByteStringAt tests
+TEST_CBOR_PARSING(SortedMapIntKeyInGetByteStringAt,
+                  "\xa1\x07\x43\x83\x03\x6B",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetByteStringAt(7), (Buffer{0x83, 0x03, 0x6B})))
+TEST_CBOR_PARSING(SortedMapEmptyStringInGetByteStringAt,
+                  "\xa1\x60\x43\x83\x03\x6B",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetByteStringAt(""), (Buffer{0x83, 0x03, 0x6B})))
+TEST_CBOR_PARSING(SortedMapCurrentIntKeyInGetByteStringAt,
+                  "\xa1\x07\x43\x83\x03\x6B",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetByteStringAt(CborParsing::CURRENT_KEY),
+                            (Buffer{0x83, 0x03, 0x6B})))
+TEST_CBOR_PARSING(SortedMapCurrentStringKeyInGetByteStringAt,
+                  "\xa1\x63\x61\x62\x63\x43\x83\x03\x6B",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetByteStringAt(CborParsing::CURRENT_KEY),
+                            (Buffer{0x83, 0x03, 0x6B})))
+TEST_CBOR_PARSING(SortedMapCurrentKeyInEmptyMapInGetByteStringAt,
+                  "\xa0",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetByteStringAt(CborParsing::CURRENT_KEY), std::nullopt))
+TEST_CBOR_PARSING(SortedMapNullValueInGetByteStringAt,
+                  "\xa1\x60\xF6",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(map.GetByteStringAt(CborParsing::CURRENT_KEY), Unknown))
+TEST_CBOR_PARSING(SortedMapUndefinedValueInGetByteStringAt,
+                  "\xa1\x60\xF7",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(map.GetByteStringAt(CborParsing::CURRENT_KEY), Unknown))
+TEST_CBOR_PARSING(SortedMapDifferentValueInGetByteStringAt,
+                  "\xa1\x60\x60",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(map.GetByteStringAt(CborParsing::CURRENT_KEY), Unknown))
+TEST_CBOR_PARSING(
+    SortedMapCurrentKeyAtEndOfMapInGetByteStringAt,
+    "\xa1\x07\x43\x83\x03\x6B",
+    auto map = parser.EnterMap(),
+    {
+        EXPECT_EQ(map.GetByteStringAt(CborParsing::CURRENT_KEY), (Buffer{0x83, 0x03, 0x6B}));
+        EXPECT_EQ(map.GetByteStringAt(CborParsing::CURRENT_KEY), std::nullopt);
+    })
+TEST_CBOR_PARSING(
+    SortedMapNonexistentIntKeyInGetByteStringAt,
+    "\xa1\x07\x43\x83\x03\x6B",
+    auto map = parser.EnterMap(),
+    {
+        EXPECT_EQ(map.GetByteStringAt(5), std::nullopt);
+        EXPECT_EQ(map.GetByteStringAt(CborParsing::CURRENT_KEY), (Buffer{0x83, 0x03, 0x6B}));
+        EXPECT_EQ(map.GetByteStringAt(42), std::nullopt);
+    })
+TEST_CBOR_PARSING(
+    SortedMapNonexistentStringKeyInGetByteStringAt,
+    "\xa1\x63\x61\x62\x63\x43\x83\x03\x6B",
+    auto map = parser.EnterMap(),
+    {
+        EXPECT_EQ(map.GetByteStringAt("xyz"), std::nullopt);
+        EXPECT_EQ(map.GetByteStringAt(CborParsing::CURRENT_KEY), (Buffer{0x83, 0x03, 0x6B}));
+        EXPECT_EQ(map.GetByteStringAt("qwe"), std::nullopt);
+    })
+TEST_CBOR_PARSING(SortedMapNullKeyInGetByteStringAt,
+                  "\xa1\xF6\x43\x83\x03\x6B",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetByteStringAt(""), std::nullopt);
+                      EXPECT_THROW(map.GetByteStringAt(CborParsing::CURRENT_KEY), Unknown);
+                  })
+TEST_CBOR_PARSING(SortedMapUndefinedKeyInGetByteStringAt,
+                  "\xa1\xF7\x43\x83\x03\x6B",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetByteStringAt(""), std::nullopt);
+                      EXPECT_THROW(map.GetByteStringAt(CborParsing::CURRENT_KEY), Unknown);
+                  })
+
+// GetBooleanAt tests
+TEST_CBOR_PARSING(SortedMapCurrentIntKeyInGetBooleanAt,
+                  "\xa1\x07\xF5",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetBooleanAt(CborParsing::CURRENT_KEY), true))
+TEST_CBOR_PARSING(SortedMapCurrentStringKeyInGetBooleanAt,
+                  "\xa1\x63\x61\x62\x63\xF5",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetBooleanAt(CborParsing::CURRENT_KEY), true))
+TEST_CBOR_PARSING(SortedMapCurrentKeyInEmptyMapInGetBooleanAt,
+                  "\xa0",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetBooleanAt(CborParsing::CURRENT_KEY), std::nullopt))
+TEST_CBOR_PARSING(SortedMapIntKeyInGetBooleanAt,
+                  "\xa1\x07\xF5",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetBooleanAt(7), true))
+TEST_CBOR_PARSING(SortedMapEmptyStringInGetBooleanAt,
+                  "\xa1\x60\xF4",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetBooleanAt(""), false))
+TEST_CBOR_PARSING(SortedMapNullValueInGetBooleanAt,
+                  "\xa1\x60\xF6",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(map.GetBooleanAt(CborParsing::CURRENT_KEY), Unknown))
+TEST_CBOR_PARSING(SortedMapUndefinedValueInGetBooleanAt,
+                  "\xa1\x60\xF7",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(map.GetBooleanAt(CborParsing::CURRENT_KEY), Unknown))
+TEST_CBOR_PARSING(SortedMapDifferentValueInGetBooleanAt,
+                  "\xa1\x60\x40",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(map.GetBooleanAt(CborParsing::CURRENT_KEY), Unknown))
+TEST_CBOR_PARSING(SortedMapCurrentKeyAtEndOfMapInGetBooleanAt,
+                  "\xa1\x07\xF5",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetBooleanAt(CborParsing::CURRENT_KEY), true);
+                      EXPECT_EQ(map.GetBooleanAt(CborParsing::CURRENT_KEY), std::nullopt);
+                  })
+TEST_CBOR_PARSING(SortedMapNonexistentIntKeyInGetBooleanAt,
+                  "\xa1\x07\xF5",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetBooleanAt(5), std::nullopt);
+                      EXPECT_EQ(map.GetBooleanAt(CborParsing::CURRENT_KEY), true);
+                      EXPECT_EQ(map.GetBooleanAt(42), std::nullopt);
+                  })
+TEST_CBOR_PARSING(SortedMapNonexistentStringKeyInGetBooleanAt,
+                  "\xa1\x63\x61\x62\x63\xF5",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetBooleanAt("xyz"), std::nullopt);
+                      EXPECT_EQ(map.GetBooleanAt(CborParsing::CURRENT_KEY), true);
+                      EXPECT_EQ(map.GetBooleanAt("qwe"), std::nullopt);
+                  })
+TEST_CBOR_PARSING(SortedMapUndefinedKeyInGetBooleanAt,
+                  "\xa1\xF7\xF5",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetBooleanAt(""), std::nullopt);
+                      EXPECT_THROW(map.GetBooleanAt(CborParsing::CURRENT_KEY), Unknown);
+                  })
+TEST_CBOR_PARSING(SortedMapNullKeyInGetBooleanAt, "\xa1\xF6\xF5", auto map = parser.EnterMap(), {
+    EXPECT_EQ(map.GetBooleanAt(""), std::nullopt);
+    EXPECT_THROW(map.GetBooleanAt(CborParsing::CURRENT_KEY), Unknown);
+})
+
+// GetUInt64At tests
+TEST_CBOR_PARSING(SortedMapIntKeyInGetUint64At,
+                  "\xa1\x07\07",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetUint64At(7), 7))
+TEST_CBOR_PARSING(SortedMapCurrentIntKeyInGetUint64At,
+                  "\xa1\x07\x07",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetUint64At(CborParsing::CURRENT_KEY), 7))
+TEST_CBOR_PARSING(SortedMapCurrentStringKeyInGetUint64At,
+                  "\xa1\x63\x61\x62\x63\x07",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetUint64At(CborParsing::CURRENT_KEY), 7))
+TEST_CBOR_PARSING(SortedMapCurrentKeyInEmptyMapInGetUint64At,
+                  "\xa0",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetUint64At(CborParsing::CURRENT_KEY), std::nullopt))
+TEST_CBOR_PARSING(SortedMapEmptyStringInGetUint64At,
+                  "\xa1\x60\x07",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.GetUint64At(""), 7))
+TEST_CBOR_PARSING(SortedMapNullValueInGetUint64At,
+                  "\xa1\x60\xF6",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(map.GetUint64At(CborParsing::CURRENT_KEY), Unknown))
+TEST_CBOR_PARSING(SortedMapUndefinedValueInGetUint64At,
+                  "\xa1\x60\xF7",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(map.GetUint64At(CborParsing::CURRENT_KEY), Unknown))
+TEST_CBOR_PARSING(SortedMapDifferentValueInGetUint64At,
+                  "\xa1\x60\x40",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(map.GetUint64At(CborParsing::CURRENT_KEY), Unknown))
+TEST_CBOR_PARSING(SortedMapCurrentKeyAtEndOfMapInGetUint64At,
+                  "\xa1\x07\x07",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetUint64At(CborParsing::CURRENT_KEY), 7);
+                      EXPECT_EQ(map.GetUint64At(CborParsing::CURRENT_KEY), std::nullopt);
+                  })
+TEST_CBOR_PARSING(SortedMapNonexistentIntKeyInGetUint64At,
+                  "\xa1\x07\x07",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetUint64At(5), std::nullopt);
+                      EXPECT_EQ(map.GetUint64At(CborParsing::CURRENT_KEY), 7);
+                      EXPECT_EQ(map.GetUint64At(42), std::nullopt);
+                  })
+TEST_CBOR_PARSING(SortedMapNonexistentStringKeyInGetUint64At,
+                  "\xa1\x63\x61\x62\x63\x07",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetUint64At("xyz"), std::nullopt);
+                      EXPECT_EQ(map.GetUint64At(CborParsing::CURRENT_KEY), 7);
+                      EXPECT_EQ(map.GetUint64At("qwe"), std::nullopt);
+                  })
+TEST_CBOR_PARSING(SortedMapUndefinedKeyInGetUint64At,
+                  "\xa1\xF7\x07",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetUint64At(""), std::nullopt);
+                      EXPECT_THROW(map.GetUint64At(CborParsing::CURRENT_KEY), Unknown);
+                  })
+TEST_CBOR_PARSING(SortedMapNullKeyInGetUint64At, "\xa1\xF6\x07", auto map = parser.EnterMap(), {
+    EXPECT_EQ(map.GetUint64At(""), std::nullopt);
+    EXPECT_THROW(map.GetUint64At(CborParsing::CURRENT_KEY), Unknown);
+})
+
+// PeekKey tests
+TEST_CBOR_PARSING(SortedMapIntKeyInPeekKey,
+                  "\xa1\x07\x07",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(std::get<int64_t>(map.PeekKey()), 7))
+TEST_CBOR_PARSING(SortedMapStringKeyInPeekKey,
+                  "\xa1\x63\x61\x62\x63\x07",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(std::get<std::string>(map.PeekKey()), "abc"))
+TEST_CBOR_PARSING(SortedMapEmptyStringKeyInPeekKey,
+                  "\xa1\x60\x07",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(std::get<std::string>(map.PeekKey()), ""))
+TEST_CBOR_PARSING(SortedMapUndefinedKeyInPeekKey,
+                  "\xa1\xF7\x07",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(map.PeekKey(), Unknown))
+TEST_CBOR_PARSING(SortedMapEmptyMapInPeekKey,
+                  "\xa0",
+                  auto map = parser.EnterMap(),
+                  ASSERT_THROW(map.PeekKey(), Unknown))
+TEST_CBOR_PARSING(SortedMapNullKeyInPeekKey,
+                  "\xa1\xF6\x07",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(std::get<std::int64_t>(map.PeekKey()), Unknown))
+TEST_CBOR_PARSING(SortedMapBoolKeyInPeekKey,
+                  "\xa1\xF4\x07",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(std::get<std::int64_t>(map.PeekKey()), Unknown))
+TEST_CBOR_PARSING(SortedMapByteStringKeyInPeekKey,
+                  "\xa1\x40\x07",
+                  auto map = parser.EnterMap(),
+                  EXPECT_THROW(std::get<std::int64_t>(map.PeekKey()), Unknown))
+TEST_CBOR_PARSING(SortedMapSecondKeyPeekInPeekKey,
+                  "\xa2\x07\x07\x08\x08",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetInt64At(7), 7);
+                      EXPECT_EQ(std::get<int64_t>(map.PeekKey()), 8);
+                  })
+TEST_CBOR_PARSING(SortedMapKeyAtTheEndOfMapInPeekKey,
+                  "\xa1\x01\x07",
+                  auto map = parser.EnterMap(),
+                  {
+                      EXPECT_EQ(map.GetInt64At(1), 7);
+                      EXPECT_THROW(std::get<int64_t>(map.PeekKey()), Unknown);
+                  })
+
+// Length tests
+TEST_CBOR_PARSING(SortedMapMapOfSize0Length,
+                  "\xa0",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.Length(), 0))
+TEST_CBOR_PARSING(SortedMapMapOfSize1Length,
+                  "\xa1\x01\x01",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.Length(), 1))
+TEST_CBOR_PARSING(SortedMapMapOfSize2Length,
+                  "\xa2\x01\x01\x02\x02",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.Length(), 2))
+TEST_CBOR_PARSING(SortedMapMapOfSize3Length,
+                  "\xa3\x01\x01\x02\x02\x03\x03",
+                  auto map = parser.EnterMap(),
+                  EXPECT_EQ(map.Length(), 3))
+TEST_CBOR_PARSING(SortedMapArrayOfSize0Length,
+                  "\x80",
+                  auto array = parser.EnterArray(),
+                  EXPECT_EQ(array.Length(), 0))
+TEST_CBOR_PARSING(SortedMapArrayOfSize1Length,
+                  "\x81\x01",
+                  auto array = parser.EnterArray(),
+                  EXPECT_EQ(array.Length(), 1))
+TEST_CBOR_PARSING(SortedMapArrayOfSize2Length,
+                  "\x82\x01\x02",
+                  auto array = parser.EnterArray(),
+                  EXPECT_EQ(array.Length(), 2))
+TEST_CBOR_PARSING(SortedMapArrayOfSize3Length,
+                  "\x83\x01\x02\x03",
+                  auto array = parser.EnterArray(),
+                  EXPECT_EQ(array.Length(), 3))
+
+// Asserts
+static_assert(&CborParsing::Parser::GetInt64 == &CborParsing::Container::GetInt64,
+              "Copy GetInt64 test from Container");
+
+static_assert(&CborParsing::Parser::GetTextString == &CborParsing::Container::GetTextString,
+              "Copy GetTextString test from Container");
+
+static_assert(&CborParsing::Parser::GetByteString == &CborParsing::Container::GetByteString,
+              "Copy GetByteString test from Container");
+
+static_assert(&CborParsing::Parser::GetBoolean == &CborParsing::Container::GetBoolean,
+              "Copy GetBoolean test from Container");
+
+static_assert(&CborParsing::Parser::GetUint64 == &CborParsing::Container::GetUint64,
+              "Copy GetUint64 test from Container");
+
+static_assert(&CborParsing::Parser::Length == &CborParsing::Container::Length,
+              "Copy Length test from Container");
+
+static_assert(&CborParsing::Parser::EnterMap == &CborParsing::Container::EnterMap,
+              "Copy EnterMap test from Container");
+
+static_assert(&CborParsing::Parser::EnterArray == &CborParsing::Container::EnterArray,
+              "Copy EnterArray test from Container");