]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/test/doc/testing_tools/boost_test_collection_comparison.qbk
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / test / doc / testing_tools / boost_test_collection_comparison.qbk
1 [/
2 / Copyright (c) 2015 Boost.Test contributors
3 /
4 / Distributed under the Boost Software License, Version 1.0. (See accompanying
5 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 /]
7
8 [section:collections Collections comparison]
9
10 Instead of comparing a single value against another, there is often a need for comparing /collections/ of values.
11 A collection and indirectly the values it contains may be considered in several ways:
12
13 * collection as a /sequence of values/: this is the case for instance when `N` values are stored in a
14 container. Containers in this case are used for storing several values, and iterating over the containers yields
15 sequences that can be compared *element-wise*. The iteration should be in an order that is /a priori/ known
16 [footnote this might not be the case
17 for e.g. `std::unordered_map`, for which the buckets might be filled differently depending on the insertion order.],
18 for being able to compare the sequences. The values in the collection are independent each other, and subsets can be compared as well.
19 * collection as an /ensemble/: this is the case where the elements of the collection define an /entity/,
20 and no element can be dissociated from the others.
21 An example would be a collection of letters for a specific word in the natural language; in this settings
22 any of the character in the word/collection depends /semantically/ on the other and it is not possible to take
23 a subset of it without breaking the meaning of the word. Another example would be a vector of size `N` representing a
24 point in a `N` dimensional space, compared to another point with the relation "`<`": the comparison is application
25 specific and a possible comparison would be the lexicographical ordering
26 [footnote in this case `v_a < v_b` means that the point `v_a` is inside the rectangle (origin, `v_b`)].
27
28 The following observations can be done:
29
30 * the methods employed for comparing collections should be chosen adequately with the meaning of the collection,
31 * comparing sequences *element-wise* often involves writing loops in the test body, and if a dedicated tool is already in place
32 the test body would gain in clarity and expressiveness (including the report in case of failure),
33 * some comparison methods such as the lexicographical one, have good general behavior (e.g. total ordering,
34 defined for collections of different size), but are sometimes inappropriate.
35
36 __BOOST_TEST__ provides specific tools for comparing collections:
37
38 * using the /native/ [footnote either defined by the container or by the user] operator of the container of the collection,
39 which is mentioned as the [link boost_test_coll_default_comp /default behavior/].
40 * using [link boost_test_coll_perelement element-wise] comparison for which extended failure diagnostic is provided,
41 * and using [link boost_test_coll_default_lex lexicographical] comparison for which extended failure diagnostic is provided,
42
43 More details about the concept of /collection/ in the __UTF__ is given [link what_is_a_collection /here/].
44
45 [#boost_test_coll_default_comp][h3 Default comparison]
46 The default comparison dispatches to the existing overloaded operator. Given two containers `c_a` and `c_b`,
47
48 ``
49 BOOST_TEST(c_a op c_b)
50 ``
51
52 is equivalent, in terms of test success, to
53
54 ``
55 auto result = c_a op c_b;
56 BOOST_TEST(result);
57 ``
58
59 In the example below, `operator==` is not defined for `std::vector` of different types, and the program would fail to
60 compile if the corresponding lines were uncommented (`std::vector` uses lexicographical comparison by default).
61
62 [note In this case, there is no additional diagnostic provided by the __UTF__. See the section
63 [link ref_boost_test_coll_special_macro `BOOST_TEST_SPECIALIZED_COLLECTION_COMPARE`] below.]
64
65 [bt_example boost_test_container_default..BOOST_TEST containers comparison default..run-fail]
66
67 [#boost_test_coll_perelement][h3 Element-wise comparison]
68 By specifying the manipulator [classref boost::test_tools::per_element], the comparison of the elements of the containers
69 are performed /element-wise/, in the order given by the forward iterators of the containers. This is a comparison on
70 the /sequences/ of elements generated by the containers, for which the __UTF__ provides advanced diagnostic.
71
72 In more details, let `c_a = (a_1,... a_n)` and `c_b = (b_1,... b_n)` be two sequences of same length, but not necessarily of same type.
73 Those sequences correspond to the content of the respective containers, in the order given by their iterator. Let
74 `op` be one of the [link boost_test_statement_overloads binary comparison operators].
75
76 ``
77 BOOST_TEST(c_a op c_b, boost::test_tools::per_element() );
78 ``
79
80 is equivalent to
81
82 ``
83 if(c_a.size() == c_b.size())
84 {
85 for(int i=0; i < c_a.size(); i++)
86 {
87 __BOOST_TEST_CONTEXT__("index " << i)
88 {
89 BOOST_TEST(a_i op b_i);
90 }
91 }
92 }
93 else
94 {
95 BOOST_TEST(c_a.size() == c_b.size());
96 }
97 ``
98
99 [warning this is fundamentally different from using the containers' default comparison operators (default behavior).]
100 [warning this is not an order relationship on containers. As a side effect, it is possible to have
101 ``BOOST_TEST(c_a == c_b)`` and ``BOOST_TEST(c_a != c_b)`` failing at the same time]
102
103 Sequences are compared using the specified operator `op`, evaluated on the left and right elements of the respective sequences.
104 The order of the compared elements is given by the iterators of the respective containers [footnote the containers should yield the same
105 sequences for a fixed set of elements they contain].
106 In case of failure, the indices of the elements failing `op` are returned.
107
108 [bt_example boost_test_sequence_per_element..BOOST_TEST sequence comparison..run-fail]
109
110 [h4 Requirements]
111 For the sequences to be comparable element-wise, the following conditions should be met:
112
113 * the containers should meet the [link what_is_a_collection sequence] definition,
114 * the containers should yield the same number of elements,
115 * `op` should be one of the comparison operator `==`, `!=`, `<`, `<=`, `>`, `>=`
116 * the `a_i op b_i` should be defined, where the type of `a_i` and `b_i` are the type returned by the dereference operator
117 of the respective collections.
118
119 [caution the resulting type of "`c_a == c_b`" is an [classref boost::test_tools::assertion_result assertion_result]: it is not
120 possible to compose more that one comparison on the `BOOST_TEST` statement:
121
122 ``
123 BOOST_TEST(c_a == c_b == 42, boost::test_tools::per_element() ); // does not compile
124 ``]
125
126 [#boost_test_coll_default_lex][h3 Lexicographic comparison]
127 By specifying the manipulator [classref boost::test_tools::lexicographic], the containers are compared using the /lexicographical/
128 order and for which the __UTF__ provides additional diagnostic in case of failure.
129
130 ``
131 BOOST_TEST(c_a op c_b, boost::test_tools::lexicographic() );
132 ``
133
134 The comparison is performed in the order given by forward iterators of the containers.
135
136 [tip lexicographic comparison yields a total order on the containers: the statements `c_a < c_b` and
137 `c_b <= c_a` are mutually exclusive.]
138
139 [bt_example boost_test_container_lex..BOOST_TEST container comparison using lexicographical order..run-fail]
140
141
142 [#ref_boost_test_coll_special_macro][h4 Extended diagnostic by default for specific containers]
143
144 As seen above, the lexicographical comparison is either explicit (`boost::test_tools::lexicographic()`) or implicit when
145 the container operations uses this type of comparison. In the second case, it is however not possible to benefit from an extended
146 diagnostic in case of failure.
147
148 If the lexicographical comparison is the default for a specific container, it is possible to dispatch the comparison
149 operations to the __UTF__ instead of the container operator. In order to default to the __UTF__ lexicographical comparison,
150 the macro `BOOST_TEST_SPECIALIZED_COLLECTION_COMPARE` might be used as follow:
151
152 [bt_example boost_test_container_lex_default..Default `std::vector<int>` to lexicographic with extended diagnostic..run-fail]
153
154 [h4 Requirements]
155
156 * the containers should meet the [link what_is_a_collection sequence] definition,
157 * the containers should be of the exact same type
158 * `op` should be one of the ordered comparison operator `<`, `<=`, `>`, `>=`
159
160
161 [#what_is_a_collection][h3 What is a sequence?]
162 A sequence is given by the iteration over a /forward iterable/ container. A forward iterable container is a container (C++11):
163
164 * that implements the member functions `size` and `begin`, as well as the fields `const_iterator` and `value_type`
165 * and for which `value_type` is not of type `char` or `wchar_t`
166
167 To that respect, C-arrays are *not* forward iterable containers:
168 [bt_example boost_test_macro_container_c_array..BOOST_TEST C-arrays..run-fail]
169
170 The detection of the containers is delegated to the class [classref boost::unit_test::is_forward_iterable], which for C++11
171 detects the required member functions and fields. However for C++03, the types providing the sequences should be explicitly indicated
172 to the __UTF__ by a specialization of [classref boost::unit_test::is_forward_iterable]
173 [footnote Standard containers of the `STL` are recognized as collections.].
174
175 [endsect] [/ sequences]