From 93cdf05928a38448a7ba0fa3e38d9f168d3ca1e1 Mon Sep 17 00:00:00 2001
From: Niels Lohmann <mail@nlohmann.me>
Date: Wed, 15 Jul 2020 14:23:22 +0200
Subject: [PATCH] :white_check_mark: add tests

---
 test/src/unit-cbor.cpp | 173 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 173 insertions(+)

diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp
index 34b57043..6af06bf6 100644
--- a/test/src/unit-cbor.cpp
+++ b/test/src/unit-cbor.cpp
@@ -2548,3 +2548,176 @@ TEST_CASE("examples from RFC 7049 Appendix A")
         CHECK(json::parse("{\"Fun\": true, \"Amt\": -2}") == json::from_cbor(std::vector<uint8_t>({0xbf, 0x63, 0x46, 0x75, 0x6e, 0xf5, 0x63, 0x41, 0x6d, 0x74, 0x21, 0xff})));
     }
 }
+
+TEST_CASE("Tagged values")
+{
+    json j = "s";
+    auto v = json::to_cbor(j);
+
+    SECTION("0xC6..0xD4")
+    {
+        for (std::uint8_t b :
+                {
+                    0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4
+                })
+        {
+            // add tag to value
+            auto v_tagged = v;
+            v_tagged.insert(v_tagged.begin(), b);
+
+            // check that parsing fails in error mode
+            CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
+            CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
+
+            // check that parsing succeeds and gets original value in ignore mode
+            auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
+            CHECK(j_tagged == j);
+        }
+    }
+
+    SECTION("0xD8 - 1 byte follows")
+    {
+        SECTION("success")
+        {
+            // add tag to value
+            auto v_tagged = v;
+            v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0xD8); // tag
+
+            // check that parsing fails in error mode
+            CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
+            CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
+
+            // check that parsing succeeds and gets original value in ignore mode
+            auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
+            CHECK(j_tagged == j);
+        }
+
+        SECTION("missing byte after tag")
+        {
+            // add tag to value
+            auto v_tagged = v;
+            v_tagged.insert(v_tagged.begin(), 0xD8); // tag
+
+            // check that parsing fails in all modes
+            CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
+            CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
+            CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
+        }
+    }
+
+    SECTION("0xD9 - 2 byte follow")
+    {
+        SECTION("success")
+        {
+            // add tag to value
+            auto v_tagged = v;
+            v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0xD9); // tag
+
+            // check that parsing fails in error mode
+            CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
+            CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
+
+            // check that parsing succeeds and gets original value in ignore mode
+            auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
+            CHECK(j_tagged == j);
+        }
+
+        SECTION("missing byte after tag")
+        {
+            // add tag to value
+            auto v_tagged = v;
+            v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0xD9); // tag
+
+            // check that parsing fails in all modes
+            CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
+            CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
+            CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
+        }
+    }
+
+    SECTION("0xDA - 4 bytes follow")
+    {
+        SECTION("success")
+        {
+            // add tag to value
+            auto v_tagged = v;
+            v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0xDA); // tag
+
+            // check that parsing fails in error mode
+            CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
+            CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
+
+            // check that parsing succeeds and gets original value in ignore mode
+            auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
+            CHECK(j_tagged == j);
+        }
+
+        SECTION("missing bytes after tag")
+        {
+            // add tag to value
+            auto v_tagged = v;
+            v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0xDA); // tag
+
+            // check that parsing fails in all modes
+            CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
+            CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
+            CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
+        }
+    }
+
+    SECTION("0xDB - 8 bytes follow")
+    {
+        SECTION("success")
+        {
+            // add tag to value
+            auto v_tagged = v;
+            v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0xDB); // tag
+
+            // check that parsing fails in error mode
+            CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
+            CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
+
+            // check that parsing succeeds and gets original value in ignore mode
+            auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
+            CHECK(j_tagged == j);
+        }
+
+        SECTION("missing byte after tag")
+        {
+            // add tag to value
+            auto v_tagged = v;
+            v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
+            v_tagged.insert(v_tagged.begin(), 0xDB); // tag
+
+            // check that parsing fails in all modes
+            CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
+            CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
+            CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
+        }
+    }
+}