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
35using tbb::flow::tuple_element;
36using tbb::flow::tuple_size;
37using tbb::flow::cast_to;
38using tbb::flow::is_a;
39
40typedef int *int_ptr;
41typedef char odd_array_type[15];
42typedef char odder_array[17];
43typedef check_type<int> counted_array_type[12];
44typedef std::vector<double> d_vector;
45typedef std::vector<int> i_vector;
46typedef i_vector i_vector_array[2];
47typedef 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
50void 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
107void 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
253int 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