From 8e43d476d35e53de10fe338e808a7c3a65e4f169 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Th=C3=A9o=20DELRIEU?= <delrieutheo@gmail.com>
Date: Tue, 13 Dec 2016 22:01:38 +0100
Subject: [PATCH] add more tests to unit-udt.cpp

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

diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp
index 2518fcfc..81fae3ee 100644
--- a/test/src/unit-udt.cpp
+++ b/test/src/unit-udt.cpp
@@ -226,3 +226,130 @@ TEST_CASE("basic usage", "[udt]")
     CHECK(book == parsed_book);
   }
 }
+
+namespace udt
+{
+template <typename T>
+class optional_type
+{
+public:
+  optional_type() = default;
+  optional_type(T t) { _impl = std::make_shared<T>(std::move(t)); }
+  optional_type(std::nullptr_t) { _impl = nullptr; }
+
+  optional_type &operator=(std::nullptr_t)
+  {
+    _impl = nullptr;
+    return *this;
+  }
+
+  optional_type& operator=(T t)
+  {
+    _impl = std::make_shared<T>(std::move(t));
+    return *this;
+  }
+
+  explicit operator bool() const noexcept { return _impl != nullptr; }
+  T const &operator*() const noexcept { return *_impl; }
+  T &operator*() noexcept { return *_impl; }
+
+private:
+  std::shared_ptr<T> _impl;
+};
+
+struct legacy_type
+{
+  std::string number;
+};
+}
+
+namespace nlohmann
+{
+template <typename T>
+struct adl_serializer<udt::optional_type<T>>
+{
+  static void to_json(json& j, udt::optional_type<T> const& opt)
+  {
+    if (opt)
+      j = *opt;
+    else
+      j = nullptr;
+  }
+
+  static void from_json(json const &j, udt::optional_type<T> &opt)
+  {
+    if (j.is_null())
+      opt = nullptr;
+    else
+      opt = j.get<T>();
+  }
+};
+
+template <>
+struct adl_serializer<udt::legacy_type>
+{
+  static void to_json(json& j, udt::legacy_type const& l)
+  {
+    j = std::stoi(l.number);
+  }
+
+  static void from_json(json const& j, udt::legacy_type& l)
+  {
+    l.number = std::to_string(j.get<int>());
+  }
+};
+}
+
+TEST_CASE("adl_serializer specialization", "[udt]")
+{
+  using nlohmann::json;
+
+  SECTION("partial specialization")
+  {
+    SECTION("to_json")
+    {
+      udt::optional_type<udt::person> optPerson;
+
+      json j = optPerson;
+      CHECK(j.is_null());
+
+      optPerson = udt::person{{42}, {"John Doe"}};
+      j = optPerson;
+      CHECK_FALSE(j.is_null());
+
+      CHECK(j.get<udt::person>() == *optPerson);
+    }
+
+    SECTION("from_json")
+    {
+      auto person = udt::person{{42}, {"John Doe"}};
+      json j = person;
+
+      auto optPerson = j.get<udt::optional_type<udt::person>>();
+      REQUIRE(optPerson);
+      CHECK(*optPerson == person);
+
+      j = nullptr;
+      optPerson = j.get<udt::optional_type<udt::person>>();
+      CHECK(!optPerson);
+    }
+  }
+
+  SECTION("total specialization")
+  {
+    SECTION("to_json")
+    {
+      udt::legacy_type lt{"4242"};
+
+      json j = lt;
+      CHECK(j.get<int>() == 4242);
+    }
+
+    SECTION("from_json")
+    {
+      json j = 4242;
+      auto lt = j.get<udt::legacy_type>();
+      CHECK(lt.number == "4242");
+    }
+  }
+}