Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / histogram / test / axis_category_test.cpp
1 // Copyright 2015-2018 Hans Dembinski
2 //
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt
5 // or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7 #include <boost/core/ignore_unused.hpp>
8 #include <boost/core/lightweight_test.hpp>
9 #include <boost/core/lightweight_test_trait.hpp>
10 #include <boost/histogram/axis/category.hpp>
11 #include <boost/histogram/axis/ostream.hpp>
12 #include <boost/histogram/axis/traits.hpp>
13 #include <limits>
14 #include <sstream>
15 #include <string>
16 #include <type_traits>
17 #include "std_ostream.hpp"
18 #include "throw_exception.hpp"
19 #include "utility_axis.hpp"
20 #include "utility_str.hpp"
21
22 int main() {
23   using namespace boost::histogram;
24
25   BOOST_TEST(std::is_nothrow_move_constructible<axis::category<int>>::value);
26   BOOST_TEST(std::is_nothrow_move_constructible<axis::category<std::string>>::value);
27   BOOST_TEST(std::is_nothrow_move_assignable<axis::category<int>>::value);
28   BOOST_TEST(std::is_nothrow_move_assignable<axis::category<std::string>>::value);
29
30   // bad ctor
31   {
32     int x[2];
33     boost::ignore_unused(x);
34     BOOST_TEST_THROWS(axis::category<int>(x + 1, x), std::invalid_argument);
35   }
36
37   // value should return copy for arithmetic types and const reference otherwise
38   {
39     enum class Foo { foo };
40
41     BOOST_TEST_TRAIT_SAME(axis::traits::value_type<axis::category<std::string>>,
42                           std::string);
43     BOOST_TEST_TRAIT_SAME(decltype(std::declval<axis::category<std::string>>().value(0)),
44                           const std::string&);
45     BOOST_TEST_TRAIT_SAME(axis::traits::value_type<axis::category<const char*>>,
46                           const char*);
47     BOOST_TEST_TRAIT_SAME(decltype(std::declval<axis::category<const char*>>().value(0)),
48                           const char*);
49     BOOST_TEST_TRAIT_SAME(axis::traits::value_type<axis::category<Foo>>, Foo);
50     BOOST_TEST_TRAIT_SAME(decltype(std::declval<axis::category<Foo>>().value(0)), Foo);
51     BOOST_TEST_TRAIT_SAME(axis::traits::value_type<axis::category<int>>, int);
52     BOOST_TEST_TRAIT_SAME(decltype(std::declval<axis::category<int>>().value(0)), int);
53   }
54
55   // empty axis::category
56   {
57     axis::category<int> a;
58     axis::category<int> b(std::vector<int>(0));
59     BOOST_TEST_EQ(a, b);
60     BOOST_TEST_EQ(a.size(), 0);
61     BOOST_TEST_EQ(a.index(-1), 0);
62     BOOST_TEST_EQ(a.index(0), 0);
63     BOOST_TEST_EQ(a.index(1), 0);
64   }
65
66   // axis::category
67   {
68     std::string A("A"), B("B"), C("C"), other;
69
70     axis::category<std::string> a({A, B, C}, "foo");
71     BOOST_TEST_EQ(a.metadata(), "foo");
72     BOOST_TEST_EQ(static_cast<const axis::category<std::string>&>(a).metadata(), "foo");
73     a.metadata() = "bar";
74     BOOST_TEST_EQ(static_cast<const axis::category<std::string>&>(a).metadata(), "bar");
75     BOOST_TEST_EQ(a.size(), 3);
76     BOOST_TEST_EQ(a.index(A), 0);
77     BOOST_TEST_EQ(a.index(B), 1);
78     BOOST_TEST_EQ(a.index(C), 2);
79     BOOST_TEST_EQ(a.index(other), 3);
80     BOOST_TEST_EQ(a.value(0), A);
81     BOOST_TEST_EQ(a.value(1), B);
82     BOOST_TEST_EQ(a.value(2), C);
83     BOOST_TEST_THROWS(a.value(3), std::out_of_range);
84
85     BOOST_TEST_EQ(str(a),
86                   "category(\"A\", \"B\", \"C\", metadata=\"bar\", options=overflow)");
87   }
88
89   // category<int, axis::null_type>: copy, move
90   {
91     using C = axis::category<int, axis::null_type>;
92     C a({1, 2, 3});
93     C a2(a);
94     BOOST_TEST_EQ(a2, a);
95     C b;
96     BOOST_TEST_NE(a, b);
97     b = a;
98     BOOST_TEST_EQ(a, b);
99     b = C{{2, 1, 3}};
100     BOOST_TEST_NE(a, b);
101     b = a;
102     BOOST_TEST_EQ(a, b);
103     C c = std::move(b);
104     BOOST_TEST_EQ(c, a);
105     C d;
106     BOOST_TEST_NE(c, d);
107     d = std::move(c);
108     BOOST_TEST_EQ(d, a);
109   }
110
111   // category<std::string>: copy, move
112   {
113     using C = axis::category<std::string>;
114
115     C a({"A", "B", "C"}, "foo");
116     C a2(a);
117     BOOST_TEST_EQ(a2, a);
118     C b;
119     BOOST_TEST_NE(a, b);
120     b = a;
121     BOOST_TEST_EQ(a, b);
122     b = C{{"B", "A", "C"}};
123     BOOST_TEST_NE(a, b);
124     b = a;
125     BOOST_TEST_EQ(a, b);
126     C c = std::move(b);
127     BOOST_TEST_EQ(c, a);
128     C d;
129     BOOST_TEST_NE(c, d);
130     d = std::move(c);
131     BOOST_TEST_EQ(d, a);
132   }
133
134   // axis::category with growth
135   {
136     axis::category<int, axis::null_type, axis::option::growth_t> a;
137     BOOST_TEST_EQ(a.size(), 0);
138     BOOST_TEST_EQ(a.update(5), std::make_pair(0, -1));
139     BOOST_TEST_EQ(a.size(), 1);
140     BOOST_TEST_EQ(a.update(1), std::make_pair(1, -1));
141     BOOST_TEST_EQ(a.size(), 2);
142     BOOST_TEST_EQ(a.update(10), std::make_pair(2, -1));
143     BOOST_TEST_EQ(a.size(), 3);
144     BOOST_TEST_EQ(a.update(10), std::make_pair(2, 0));
145     BOOST_TEST_EQ(a.size(), 3);
146
147     BOOST_TEST_EQ(str(a), "category(5, 1, 10, options=growth)");
148   }
149
150   // iterators
151   {
152     test_axis_iterator(axis::category<>({3, 1, 2}, ""), 0, 3);
153     test_axis_iterator(axis::category<std::string>({"A", "B"}, ""), 0, 2);
154   }
155
156   return boost::report_errors();
157 }