1 /*
2 Copyright (c) 2005-2021 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18 #define _VARIADIC_MAX 10 // Visual Studio 2012
19 #include "common/config.h"
20
21 #include "tbb/flow_graph.h"
22
23 #include "common/test.h"
24 #include "common/checktype.h"
25
26 #include <cstdio>
27 #include <atomic>
28 #include <tuple>
29 #include <stdexcept>
30 #include <vector>
31
32
33 //! \file test_tagged_msg.cpp
34 //! \brief Test for [flow_graph.tagged_msg] specification
35
36
37 // given a tuple, return the type of the element that has the maximum alignment requirement.
38 // Given a tuple and that type, return the number of elements of the object with the max
39 // alignment requirement that is at least as big as the largest object in the tuple.
40
41 using std::tuple_element;
42 using std::tuple_size;
43 using tbb::flow::cast_to;
44 using tbb::flow::is_a;
45
46 typedef int *int_ptr;
47 typedef char odd_array_type[15];
48 typedef char odder_array[17];
49 typedef CheckType<int> counted_array_type[12];
50 typedef std::vector<double> d_vector;
51 typedef std::vector<int> i_vector;
52 typedef i_vector i_vector_array[2];
53 typedef tbb::flow::tagged_msg<size_t, int, char, double, odd_array_type, odder_array, d_vector, CheckType<int>, counted_array_type, i_vector_array> tagged_msg_type;
54
55 // test base of tagged_msg
TestWrapper()56 void TestWrapper() {
57 using tbb::detail::d1::Wrapper;
58 Wrapper<int> wi(42);
59 Wrapper<int> wic(23);
60
61 INFO("Value of wic is " << wic.value() << "\n");
62
63 // pointer-type creation
64 int point_to_me = 23;
65 Wrapper<int_ptr> wip(&point_to_me);
66 CHECK_MESSAGE( (*(wip.value()) == 23), "Error in wip value");
67
68 odd_array_type ww;
69 for(int ii = 0; ii < 15; ++ii) { ww[ii] = char('0' + ii); } ww[14] = 0;
70
71 Wrapper<odd_array_type> ci(ww);
72 CHECK_MESSAGE( (!strncmp(ci.value(), ww, 14)), "odd_array_type ci not properly-constructed" );
73
74 Wrapper<odd_array_type> ci2(ci);
75
76 CHECK_MESSAGE( (!strncmp(ci2.value(), ww, 14)), "odd_array_type ci2 not properly-constructed" );
77
78 d_vector di;
79 di.clear();
80 di.push_back(2.0);
81 Wrapper<d_vector> dvec(di);
82 CHECK_MESSAGE( (dvec.value()[0] == 2.0), "incorrect value in vector");
83
84 // test array of non-PODs.
85 i_vector_array oia;
86 oia[0].clear();
87 oia[1].clear();
88 oia[0].push_back(3);
89 oia[1].push_back(2);
90 Wrapper<i_vector_array> ia(oia);
91 CHECK_MESSAGE( ((ia.value()[1])[0] == 2), "integer vector array element[1] misbehaved");
92 CHECK_MESSAGE( ((ia.value()[0])[0] == 3), "integer vector array element[0] misbehaved");
93 Wrapper<i_vector_array> iac(ia);
94 CHECK_MESSAGE( ((iac.value()[1])[0] == 2), "integer vector array element[1] misbehaved");
95 CHECK_MESSAGE( ((iac.value()[0])[0] == 3), "integer vector array element[0] misbehaved");
96
97 // counted_array
98 counted_array_type cat_orig;
99 for(int i = 0; i < 12; ++i) cat_orig[i] = i + 1;
100 Wrapper<counted_array_type> cat(cat_orig);
101 for(int j = 0; j < 12; ++j)
102 CHECK_MESSAGE( (1 + j == cat.value()[j]), "Error in cat array");
103
104 int i = wi.value();
105 CHECK_MESSAGE( (i == 42), "Assignment to i failed");
106 CHECK_MESSAGE( (wi.value() == 42), "Assignment to wi failed");
107 double d = wi.value();
108 CHECK_MESSAGE( (d == 42), "Implicit cast in assign to double failed");
109 int_ptr ip = wip.value();
110 CHECK_MESSAGE( (ip == &(point_to_me)), "Error in assignment of pointer");
111 }
112
RunTests()113 void RunTests() {
114 tagged_msg_type def;
115 tagged_msg_type i(1,3);
116 CheckType<int>::check_type_counter = 0;
117 int z;
118 #if TBB_USE_EXCEPTIONS
119 try {
120 z = cast_to<int>(def); // disallowed (non-array returning int)
121 CHECK_MESSAGE( (false), "should not allow cast to int of non-array");
122 }
123 catch(...) {
124 INFO("cast of non-array to int disallowed (okay)\n");
125 }
126 #endif
127 z = cast_to<int>(i);
128 CHECK_MESSAGE( (is_a<int>(i)), "wrong type for i ( == int)");
129 CHECK_MESSAGE( (!(is_a<double>(i))), "Wrong type for i ( != double)");
130 z = 5;
131 z = cast_to<int>(i);
132
133 const int &ref_i(cast_to<int>(i));
134 CHECK_MESSAGE( (ref_i == 3), "ref_i got wrong value");
135 tagged_msg_type j(2,4);
136 i = j;
137 CHECK_MESSAGE( (ref_i == 4), "assign to i did not affect ref_i");
138
139 CHECK_MESSAGE( ( z == 3), "Error retrieving value from i");
140
141 //updating and retrieving tags
142 CHECK_MESSAGE( (j.tag() == 2), "Error retrieving tag for j");
143 j.set_tag(10);
144 CHECK_MESSAGE( (j.tag() == 10), "Error updating tag for j");
145
146 tbb::flow::tagged_msg<char, int, char, double> k('a', 4);
147 k.set_tag('b');
148 CHECK_MESSAGE( (k.tag() == 'b'), "Error updating char tag");
149
150 tagged_msg_type double_tagged_msg(3, 8.0);
151 CHECK_MESSAGE( (is_a<double>(double_tagged_msg)), "Wrong type for double_tagged_msg (== double)");
152 CHECK_MESSAGE( (!is_a<char>(double_tagged_msg)), "Wrong type for double_tagged_msg (!= char)");
153 CHECK_MESSAGE( (!is_a<int>(double_tagged_msg)), "Wrong type for double_tagged_msg (!= int)");
154 tagged_msg_type copytype(double_tagged_msg);
155 CHECK_MESSAGE( (is_a<double>(copytype)), "Wrong type for double_tagged_msg (== double)");
156 CHECK_MESSAGE( (!is_a<char>(copytype)), "Wrong type for double_tagged_msg (!= char)");
157 CHECK_MESSAGE( (!is_a<int>(copytype)), "Wrong type for double_tagged_msg (!= int)");
158 tagged_msg_type default_tagged_msg;
159 CHECK_MESSAGE( (!(is_a<double>(default_tagged_msg))), "wrong type for default ( != double)");
160 CHECK_MESSAGE( (!(is_a<int>(default_tagged_msg))), "wrong type for default ( != int)");
161 CHECK_MESSAGE( (!(is_a<bool>(default_tagged_msg))), "wrong type for default ( != bool)");
162 CheckType<int> c;
163 CHECK_MESSAGE( (CheckType<int>::check_type_counter == 1), "Incorrect number of CheckType<int>s created");
164 tagged_msg_type cnt_type(4, c);
165 CHECK_MESSAGE( (CheckType<int>::check_type_counter == 2), "Incorrect number of CheckType<int>s created");
166 CHECK_MESSAGE( (is_a<CheckType<int> >(cnt_type)), "Incorrect type for cnt_type");
167 cnt_type = default_tagged_msg;
168 CHECK_MESSAGE( (CheckType<int>::check_type_counter == 1), "Incorrect number of CheckType<int>s after reassignment");
169 CHECK_MESSAGE( (cnt_type.is_default_constructed()), "Assigned CheckType<int>s is not default-constructed");
170 // having problem with init on gcc 3.4.6 (fxeolin16) constructor for elements of array not called
171 // for this version.
172 // counted_array_type counted_array;
173 CheckType<int> counted_array[12]; // this is okay
174 CHECK_MESSAGE( (CheckType<int>::check_type_counter == 13), "Incorrect number of CheckType<int>s after counted_array construction");
175 tagged_msg_type counted_array_tagged_msg(5, counted_array);
176 // the is_a<>() should return exact type matches.
177 CHECK_MESSAGE( (!is_a<CheckType<int> *>(counted_array_tagged_msg)), "Test of is_a for counted_array_tagged_msg fails");
178 #if TBB_USE_EXCEPTIONS
179 try {
180 int *iip = cast_to<int *>(counted_array_tagged_msg);
181 CHECK_MESSAGE( (false), "did not throw on invalid cast");
182 *iip = 2; // avoids "iip set but not used" warning
183 }
184 catch(std::runtime_error &re) {
185 INFO("attempt to cast to invalid type caught " << re.what() << "\n");
186 }
187 CHECK_MESSAGE( (is_a<counted_array_type>(counted_array_tagged_msg)), "testing");
188 const CheckType<int> *ctip = cast_to<counted_array_type>(counted_array_tagged_msg);
189
190 CHECK_MESSAGE( ((int)(*ctip) == 0), "ctip incorrect");
191
192 CHECK_MESSAGE( (CheckType<int>::check_type_counter == 25), "Incorrect number of CheckType<int>s after counted_array_tagged_msg construction");
193 counted_array_tagged_msg = default_tagged_msg;
194 CHECK_MESSAGE( (CheckType<int>::check_type_counter == 13), "Incorrect number of CheckType<int>s after counted_array_tagged_msg destruction");
195 CHECK_MESSAGE( (counted_array_tagged_msg.is_default_constructed()), "Assigned counted_array_type is not default-constructed");
196
197 default_tagged_msg = double_tagged_msg;
198 const double my_dval = cast_to<double>(default_tagged_msg);
199 CHECK_MESSAGE( (my_dval == 8.0), "did not retrieve correct value from assigned default_tagged_msg");
200
201 {
202 odd_array_type my_b;
203 for(size_t ii=0; ii < 14;++ii) {
204 my_b[ii] = (char)('0' + ii);
205 }
206 my_b[14] = 0;
207 {
208 tagged_msg_type odd_array_tagged_msg(6, my_b);
209 const char *my_copy = cast_to<odd_array_type>(odd_array_tagged_msg);
210 CHECK_MESSAGE( (!strncmp(my_b, my_copy, 14)), "copied char array not correct value");
211 default_tagged_msg = odd_array_tagged_msg;
212 try {
213 const char *my_copy2 = cast_to<odd_array_type>(default_tagged_msg);
214 CHECK_MESSAGE( (!strncmp(my_b, my_copy2, 14)), "char array from default tagged_msg assign not correct value");
215 }
216 catch(...) {
217 CHECK_MESSAGE( (false), "Bad cast");
218 }
219 }
220 }
221
222 CHECK_MESSAGE( (!is_a<double>(i)), "bad type for i");
223 try {
224 double y = cast_to<double>(i);
225 // use '&' to force eval of RHS (fixes "initialized but not referenced" vs2012 warnings)
226 CHECK_MESSAGE( (false & (0 != y)), "Error: cast to type in tuple did not get exception");
227 }
228 catch(std::runtime_error &bc) {
229 CHECK_MESSAGE( (0 == strcmp(bc.what(), "Illegal tagged_msg cast")), "Incorrect std:runtime_error");
230 }
231 catch(...) {
232 CHECK_MESSAGE( (false & cast_to<int>(i)), "Error: improper exception thrown");
233 }
234
235 try {
236 int *ip = cast_to<int *>(i);
237 CHECK_MESSAGE( (false & (NULL!=ip)), "Error: non-array cast to pointer type.");
238 }
239 catch(std::runtime_error &bc) {
240 CHECK_MESSAGE( (0 == strcmp(bc.what(), "Illegal tagged_msg cast")), "Incorrect std:runtime_error");
241 }
242 catch(...) {
243 CHECK_MESSAGE( (false), "did not get runtime_error exception in casting non-array to pointer");
244 }
245
246 try {
247 bool b = cast_to<bool>(i);
248 CHECK_MESSAGE( (false & b), "Error: cast against type did not get exception");
249 }
250 catch(std::runtime_error &bc) {
251 CHECK_MESSAGE( (0 == strcmp(bc.what(), "Illegal tagged_msg cast")), "Incorrect std:runtime_error");
252 }
253 catch(...) {
254 CHECK_MESSAGE( (false), "did not get runtime_error exception casting to disparate types");
255 }
256 #endif //TBB_USE_EXCEPTIONS
257 }
258
259 //! Test tagged_msg for specific types
260 //! \brief \ref error_guessing
261 TEST_CASE("Test base of tagged_msg") {
262 TestWrapper();
263 CHECK_MESSAGE( (CheckType<int>::check_type_counter == 0), "After TestWrapper return not all CheckType<int>s were destroyed");
264 }
265
266 //! Test tagged_msg functions and exceptional behavior
267 //! \brief \ref requirement \ref error_guessing
268 TEST_CASE("Test tagged_msg") {
269 RunTests();
270 CHECK_MESSAGE( (CheckType<int>::check_type_counter == 0), "After RunTests return not all CheckType<int>s were destroyed");
271 }
272