1 /*
2  * ====================================================================
3  *    Licensed to the Apache Software Foundation (ASF) under one
4  *    or more contributor license agreements.  See the NOTICE file
5  *    distributed with this work for additional information
6  *    regarding copyright ownership.  The ASF licenses this file
7  *    to you under the Apache License, Version 2.0 (the
8  *    "License"); you may not use this file except in compliance
9  *    with the License.  You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *    Unless required by applicable law or agreed to in writing,
14  *    software distributed under the License is distributed on an
15  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  *    KIND, either express or implied.  See the License for the
17  *    specific language governing permissions and limitations
18  *    under the License.
19  * ====================================================================
20  */
21 
22 #include <boost/test/unit_test.hpp>
23 
24 #include <algorithm>
25 #include <stdexcept>
26 
27 #include "../src/aprwrap.hpp"
28 
29 #include "fixture_init.hpp"
30 
31 BOOST_AUTO_TEST_SUITE(aprwrap_arrays,
32                       * boost::unit_test::fixture<init>());
33 
34 namespace {
35 // Create a randomly-ordered array of constant strings.
fill_array(apr::pool & pool)36 apr_array_header_t* fill_array(apr::pool& pool)
37 {
38   apr_array_header_t* a = apr_array_make(pool.get(), 0, sizeof(const char*));
39   APR_ARRAY_PUSH(a, const char*) = "primus";
40   APR_ARRAY_PUSH(a, const char*) = "secundus";
41   APR_ARRAY_PUSH(a, const char*) = "tertius";
42   APR_ARRAY_PUSH(a, const char*) = "quartus";
43   APR_ARRAY_PUSH(a, const char*) = "quintus";
44   APR_ARRAY_PUSH(a, const char*) = "sextus";
45   APR_ARRAY_PUSH(a, const char*) = "septimus";
46   std::random_shuffle(&APR_ARRAY_IDX(a, 0, const char*),
47                       &APR_ARRAY_IDX(a, a->nelts, const char*));
48   return a;
49 }
50 } // anonymous namespace
51 
BOOST_AUTO_TEST_CASE(create_array)52 BOOST_AUTO_TEST_CASE(create_array)
53 {
54   typedef apr::array<unsigned char> array;
55 
56   apr::pool pool;
57   array a(pool);
58 
59   BOOST_TEST(a.get_array() != nullptr);
60   BOOST_TEST(a.size() == 0);
61   BOOST_TEST(sizeof(array::value_type) == sizeof(unsigned char));
62   BOOST_TEST(a.get_array()->elt_size == sizeof(array::value_type));
63 }
64 
BOOST_AUTO_TEST_CASE(wrap_array)65 BOOST_AUTO_TEST_CASE(wrap_array)
66 {
67   typedef apr::array<unsigned char> array;
68 
69   apr::pool pool;
70   apr_array_header_t* apr_array =
71     apr_array_make(pool.get(), 0, sizeof(array::value_type));
72   BOOST_TEST_REQUIRE(apr_array != nullptr);
73 
74   array a(apr_array);
75   BOOST_TEST(a.get_array() == apr_array);
76   BOOST_TEST(a.size() == 0);
77 }
78 
BOOST_AUTO_TEST_CASE(rewrap_type_mismatch)79 BOOST_AUTO_TEST_CASE(rewrap_type_mismatch)
80 {
81   typedef apr::array<unsigned char> byte_array;
82   typedef apr::array<int> int_array;
83 
84   apr::pool pool;
85   BOOST_CHECK_THROW(byte_array{int_array(pool).get_array()},
86                     std::invalid_argument);
87 }
88 
BOOST_AUTO_TEST_CASE(out_of_bounds)89 BOOST_AUTO_TEST_CASE(out_of_bounds)
90 {
91   typedef apr::array<unsigned char> array;
92 
93   apr::pool pool;
94   array a(pool);
95 
96   BOOST_CHECK_THROW(a.at(-1), std::out_of_range);
97   BOOST_CHECK_THROW(a.at(a.size()), std::out_of_range);
98 }
99 
BOOST_AUTO_TEST_CASE(indexing)100 BOOST_AUTO_TEST_CASE(indexing)
101 {
102   typedef apr::array<const char*> array;
103 
104   apr::pool pool;
105   array a(fill_array(pool));
106 
107   BOOST_TEST(a[0] == APR_ARRAY_IDX(a.get_array(), 0, array::value_type));
108   BOOST_TEST(a[a.size() - 1] == APR_ARRAY_IDX(a.get_array(),
109                                               a.get_array()->nelts - 1,
110                                               array::value_type));
111 }
112 
BOOST_AUTO_TEST_CASE(checked_indexing)113 BOOST_AUTO_TEST_CASE(checked_indexing)
114 {
115   typedef apr::array<const char*> array;
116 
117   apr::pool pool;
118   array a(fill_array(pool));
119 
120   BOOST_TEST(a.at(0) == APR_ARRAY_IDX(a.get_array(), 0, array::value_type));
121   BOOST_TEST(a.at(a.size() - 1) == APR_ARRAY_IDX(a.get_array(),
122                                                  a.get_array()->nelts - 1,
123                                                  array::value_type));
124 }
125 
BOOST_AUTO_TEST_CASE(iteration)126 BOOST_AUTO_TEST_CASE(iteration)
127 {
128   typedef apr::array<const char*> array;
129 
130   apr::pool pool;
131   array a(fill_array(pool));
132 
133   const auto raw_array = a.get_array();
134   array::size_type index = 0;
135   for (auto& value : a)
136     {
137       BOOST_TEST(value == APR_ARRAY_IDX(raw_array, index, array::value_type));
138       ++index;
139     }
140 }
141 
BOOST_AUTO_TEST_CASE(const_iteration)142 BOOST_AUTO_TEST_CASE(const_iteration)
143 {
144   typedef apr::array<const char*> array;
145 
146   apr::pool pool;
147   const array a(fill_array(pool));
148 
149   const auto raw_array = a.get_array();
150   array::size_type index = 0;
151   for (const auto& value : a)
152     {
153       BOOST_TEST(value == APR_ARRAY_IDX(raw_array, index, array::value_type));
154       ++index;
155     }
156 }
157 
BOOST_AUTO_TEST_CASE(push)158 BOOST_AUTO_TEST_CASE(push)
159 {
160   typedef apr::array<const char*> array;
161 
162   apr::pool pool;
163   array a(fill_array(pool));
164 
165   const array::size_type point = a.size();
166   const array::value_type first = a[0];
167   const array::value_type last = a[point - 1];
168 
169   a.push("octavius");
170   a.push("nonus");
171   a.push("decimus");
172 
173   BOOST_TEST(a.size() == point + 3);
174   BOOST_TEST(a[0] == first);
175   BOOST_TEST(a[point - 1] == last);
176   BOOST_TEST(a[point] == "octavius");
177   BOOST_TEST(a[a.size() - 1] == "decimus");
178 }
179 
BOOST_AUTO_TEST_CASE(pop)180 BOOST_AUTO_TEST_CASE(pop)
181 {
182   typedef apr::array<const char*> array;
183 
184   apr::pool pool;
185   array a(fill_array(pool));
186 
187   for (array::size_type i = 0, z = a.size(); i <= z; ++i)
188     {
189       const char** last = (!a.get_array()->nelts ? nullptr
190                            : &APR_ARRAY_IDX(a.get_array(),
191                                             a.get_array()->nelts - 1,
192                                             array::value_type));
193       BOOST_TEST(a.pop() == last);
194     }
195 }
196 
197 BOOST_AUTO_TEST_SUITE_END();
198