• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/lightweight_test.hpp>
8 #include <boost/core/lightweight_test_trait.hpp>
9 #include <boost/histogram/axis/category.hpp>
10 #include <boost/histogram/axis/ostream.hpp>
11 #include <boost/histogram/axis/traits.hpp>
12 #include <limits>
13 #include <sstream>
14 #include <string>
15 #include <type_traits>
16 #include "std_ostream.hpp"
17 #include "throw_exception.hpp"
18 #include "utility_axis.hpp"
19 #include "utility_str.hpp"
20 
main()21 int main() {
22   using namespace boost::histogram;
23 
24   BOOST_TEST(std::is_nothrow_move_constructible<axis::category<int>>::value);
25   BOOST_TEST(std::is_nothrow_move_constructible<axis::category<std::string>>::value);
26   BOOST_TEST(std::is_nothrow_move_assignable<axis::category<int>>::value);
27   BOOST_TEST(std::is_nothrow_move_assignable<axis::category<std::string>>::value);
28 
29   // bad ctor
30   {
31     int x[2];
32     (void)x;
33     BOOST_TEST_THROWS(axis::category<int>(x + 1, x), std::invalid_argument);
34   }
35 
36   // value should return copy for arithmetic types and const reference otherwise
37   {
38     enum class Foo { foo };
39 
40     BOOST_TEST_TRAIT_SAME(axis::traits::value_type<axis::category<std::string>>,
41                           std::string);
42     BOOST_TEST_TRAIT_SAME(decltype(std::declval<axis::category<std::string>>().value(0)),
43                           const std::string&);
44     BOOST_TEST_TRAIT_SAME(axis::traits::value_type<axis::category<const char*>>,
45                           const char*);
46     BOOST_TEST_TRAIT_SAME(decltype(std::declval<axis::category<const char*>>().value(0)),
47                           const char*);
48     BOOST_TEST_TRAIT_SAME(axis::traits::value_type<axis::category<Foo>>, Foo);
49     BOOST_TEST_TRAIT_SAME(decltype(std::declval<axis::category<Foo>>().value(0)), Foo);
50     BOOST_TEST_TRAIT_SAME(axis::traits::value_type<axis::category<int>>, int);
51     BOOST_TEST_TRAIT_SAME(decltype(std::declval<axis::category<int>>().value(0)), int);
52   }
53 
54   // empty axis::category
55   {
56     axis::category<int> a;
57     axis::category<int> b(std::vector<int>(0));
58     BOOST_TEST_EQ(a, b);
59     BOOST_TEST_EQ(a.size(), 0);
60     BOOST_TEST_EQ(a.index(-1), 0);
61     BOOST_TEST_EQ(a.index(0), 0);
62     BOOST_TEST_EQ(a.index(1), 0);
63   }
64 
65   // axis::category
66   {
67     std::string A("A"), B("B"), C("C"), other;
68 
69     axis::category<std::string> a({A, B, C}, "foo");
70     BOOST_TEST_EQ(a.metadata(), "foo");
71     BOOST_TEST_EQ(static_cast<const axis::category<std::string>&>(a).metadata(), "foo");
72     a.metadata() = "bar";
73     BOOST_TEST_EQ(static_cast<const axis::category<std::string>&>(a).metadata(), "bar");
74     BOOST_TEST_EQ(a.size(), 3);
75     BOOST_TEST_EQ(a.index(A), 0);
76     BOOST_TEST_EQ(a.index(B), 1);
77     BOOST_TEST_EQ(a.index(C), 2);
78     BOOST_TEST_EQ(a.index(other), 3);
79     BOOST_TEST_EQ(a.value(0), A);
80     BOOST_TEST_EQ(a.value(1), B);
81     BOOST_TEST_EQ(a.value(2), C);
82     BOOST_TEST_THROWS(a.value(3), std::out_of_range);
83 
84     BOOST_TEST_CSTR_EQ(
85         str(a).c_str(),
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     using pii_t = std::pair<axis::index_type, axis::index_type>;
137     axis::category<int, axis::null_type, axis::option::growth_t> a;
138     BOOST_TEST_EQ(a.size(), 0);
139     BOOST_TEST_EQ(a.update(5), pii_t(0, -1));
140     BOOST_TEST_EQ(a.size(), 1);
141     BOOST_TEST_EQ(a.update(1), pii_t(1, -1));
142     BOOST_TEST_EQ(a.size(), 2);
143     BOOST_TEST_EQ(a.update(10), pii_t(2, -1));
144     BOOST_TEST_EQ(a.size(), 3);
145     BOOST_TEST_EQ(a.update(10), pii_t(2, 0));
146     BOOST_TEST_EQ(a.size(), 3);
147 
148     BOOST_TEST_EQ(str(a), "category(5, 1, 10, options=growth)");
149   }
150 
151   // iterators
152   {
153     test_axis_iterator(axis::category<>({3, 1, 2}, ""), 0, 3);
154     test_axis_iterator(axis::category<std::string>({"A", "B"}, ""), 0, 2);
155   }
156 
157   return boost::report_errors();
158 }
159