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