1//     __ _____ _____ _____
2//  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
3// |  |  |__   |  |  | | | |  version 3.11.2
4// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9#include "doctest_compatibility.h"
10
11#include <nlohmann/json.hpp>
12using nlohmann::json;
13
14TEST_CASE("concepts")
15{
16    SECTION("container requirements for json")
17    {
18        // X: container class: json
19        // T: type of objects: json
20        // a, b: values of type X: json
21
22        // TABLE 96 - Container Requirements
23
24        // X::value_type must return T
25        CHECK((std::is_same<json::value_type, json>::value));
26
27        // X::reference must return lvalue of T
28        CHECK((std::is_same<json::reference, json&>::value));
29
30        // X::const_reference must return const lvalue of T
31        CHECK((std::is_same<json::const_reference, const json&>::value));
32
33        // X::iterator must return iterator whose value_type is T
34        CHECK((std::is_same<json::iterator::value_type, json>::value));
35        // X::iterator must meet the forward iterator requirements
36        CHECK((std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<json::iterator>::iterator_category>::value));
37        // X::iterator must be convertible to X::const_iterator
38        CHECK((std::is_convertible<json::iterator, json::const_iterator>::value));
39
40        // X::const_iterator must return iterator whose value_type is T
41        CHECK((std::is_same<json::const_iterator::value_type, json>::value));
42        // X::const_iterator must meet the forward iterator requirements
43        CHECK((std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<json::const_iterator>::iterator_category>::value));
44
45        // X::difference_type must return a signed integer
46        CHECK((std::is_signed<json::difference_type>::value));
47        // X::difference_type must be identical to X::iterator::difference_type
48        CHECK((std::is_same<json::difference_type, json::iterator::difference_type>::value));
49        // X::difference_type must be identical to X::const_iterator::difference_type
50        CHECK((std::is_same<json::difference_type, json::const_iterator::difference_type>::value));
51
52        // X::size_type must return an unsigned integer
53        CHECK((std::is_unsigned<json::size_type>::value));
54        // X::size_type can represent any non-negative value of X::difference_type
55        CHECK(static_cast<json::size_type>((std::numeric_limits<json::difference_type>::max)()) <=
56              (std::numeric_limits<json::size_type>::max)());
57
58        // the expression "X u" has the post-condition "u.empty()"
59        {
60            json u;
61            CHECK(u.empty());
62        }
63
64        // the expression "X()" has the post-condition "X().empty()"
65        CHECK(json().empty());
66    }
67
68    SECTION("class json")
69    {
70        SECTION("DefaultConstructible")
71        {
72            CHECK(std::is_nothrow_default_constructible<json>::value);
73        }
74
75        SECTION("MoveConstructible")
76        {
77            CHECK(std::is_move_constructible<json>::value);
78            CHECK(std::is_nothrow_move_constructible<json>::value);
79        }
80
81        SECTION("CopyConstructible")
82        {
83            CHECK(std::is_copy_constructible<json>::value);
84        }
85
86        SECTION("MoveAssignable")
87        {
88            CHECK(std::is_nothrow_move_assignable<json>::value);
89        }
90
91        SECTION("CopyAssignable")
92        {
93            CHECK(std::is_copy_assignable<json>::value);
94        }
95
96        SECTION("Destructible")
97        {
98            CHECK(std::is_nothrow_destructible<json>::value);
99        }
100
101        SECTION("StandardLayoutType")
102        {
103            CHECK(std::is_standard_layout<json>::value);
104        }
105    }
106
107    SECTION("class iterator")
108    {
109        SECTION("CopyConstructible")
110        {
111            CHECK(std::is_nothrow_copy_constructible<json::iterator>::value);
112            CHECK(std::is_nothrow_copy_constructible<json::const_iterator>::value);
113        }
114
115        SECTION("CopyAssignable")
116        {
117            // STL iterators used by json::iterator don't pass this test in Debug mode
118#if !defined(_MSC_VER) || (_ITERATOR_DEBUG_LEVEL == 0)
119            CHECK(std::is_nothrow_copy_assignable<json::iterator>::value);
120            CHECK(std::is_nothrow_copy_assignable<json::const_iterator>::value);
121#endif
122        }
123
124        SECTION("Destructible")
125        {
126            CHECK(std::is_nothrow_destructible<json::iterator>::value);
127            CHECK(std::is_nothrow_destructible<json::const_iterator>::value);
128        }
129
130        SECTION("Swappable")
131        {
132            {
133                json j {1, 2, 3};
134                json::iterator it1 = j.begin();
135                json::iterator it2 = j.end();
136                swap(it1, it2);
137                CHECK(it1 == j.end());
138                CHECK(it2 == j.begin());
139            }
140            {
141                json j {1, 2, 3};
142                json::const_iterator it1 = j.cbegin();
143                json::const_iterator it2 = j.cend();
144                swap(it1, it2);
145                CHECK(it1 == j.end());
146                CHECK(it2 == j.begin());
147            }
148        }
149    }
150}
151