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 | #ifndef __TBB_test_initializer_list_H |
18 | #define __TBB_test_initializer_list_H |
19 | #include "tbb/tbb_config.h" |
20 | |
21 | #if __TBB_INITIALIZER_LISTS_PRESENT |
22 | #include <initializer_list> |
23 | #include <vector> |
24 | #include "harness_defs.h" //for int_to_type |
25 | |
26 | namespace initializer_list_support_tests{ |
27 | template<typename container_type, typename element_type> |
28 | void test_constructor(std::initializer_list<element_type> il, container_type const& expected){ |
29 | container_type vd (il); |
30 | ASSERT(vd == expected,"initialization via explicit constructor call with init list failed" ); |
31 | } |
32 | |
33 | |
34 | template<typename container_type, typename element_type> |
35 | void test_assignment_operator(std::initializer_list<element_type> il, container_type const& expected){ |
36 | container_type va; |
37 | va = il; |
38 | ASSERT(va == expected,"init list operator= failed" ); |
39 | } |
40 | |
41 | struct skip_test { |
42 | template<typename container_type, typename element_type> |
43 | static void do_test(std::initializer_list<element_type>, container_type const&) { /* do nothing */ } |
44 | }; |
45 | |
46 | struct test_assign { |
47 | template<typename container_type, typename element_type> |
48 | static void do_test( std::initializer_list<element_type> il, container_type const& expected ) { |
49 | container_type vae; |
50 | vae.assign( il ); |
51 | ASSERT( vae == expected, "init list assign(begin,end) failed" ); |
52 | } |
53 | }; |
54 | |
55 | struct test_special_insert { |
56 | template<typename container_type, typename element_type> |
57 | static void do_test( std::initializer_list<element_type> il, container_type const& expected ) { |
58 | container_type vd; |
59 | vd.insert( il ); |
60 | ASSERT( vd == expected, "inserting with an initializer list failed" ); |
61 | } |
62 | }; |
63 | |
64 | template <typename container_type, typename test_assign, typename test_special> |
65 | void TestInitListSupport(std::initializer_list<typename container_type::value_type> il){ |
66 | typedef typename container_type::value_type element_type; |
67 | std::vector<element_type> test_seq(il.begin(),il.end()); |
68 | container_type expected(test_seq.begin(), test_seq.end()); |
69 | |
70 | test_constructor<container_type,element_type>(il, expected); |
71 | test_assignment_operator<container_type,element_type>(il, expected); |
72 | test_assign::do_test(il, expected); |
73 | test_special::do_test(il, expected); |
74 | } |
75 | |
76 | template <typename container_type, typename test_special = skip_test> |
77 | void TestInitListSupport(std::initializer_list<typename container_type::value_type> il) { |
78 | TestInitListSupport<container_type, test_assign, test_special>(il); |
79 | } |
80 | |
81 | template <typename container_type, typename test_special = skip_test> |
82 | void TestInitListSupportWithoutAssign(std::initializer_list<typename container_type::value_type> il){ |
83 | TestInitListSupport<container_type, skip_test, test_special>(il); |
84 | } |
85 | |
86 | //TODO: add test for no leaks, and correct element lifetime |
87 | //the need for macro comes from desire to test different scenarios where initializer sequence is compile time constant |
88 | #define __TBB_TEST_INIT_LIST_SUITE_SINGLE(FUNC_NAME, CONTAINER, ELEMENT_TYPE, INIT_SEQ) \ |
89 | void FUNC_NAME(){ \ |
90 | typedef ELEMENT_TYPE element_type; \ |
91 | typedef CONTAINER<element_type> container_type; \ |
92 | element_type test_seq[] = INIT_SEQ; \ |
93 | container_type expected(test_seq,test_seq + Harness::array_length(test_seq)); \ |
94 | \ |
95 | /*test for explicit constructor call*/ \ |
96 | container_type vd INIT_SEQ; \ |
97 | ASSERT(vd == expected,"initialization via explicit constructor call with init list failed"); \ |
98 | /*test for explicit constructor call with std::initializer_list*/ \ |
99 | \ |
100 | std::initializer_list<element_type> init_list = INIT_SEQ; \ |
101 | container_type v1 (init_list); \ |
102 | ASSERT(v1 == expected,"initialization via explicit constructor call with std::initializer_list failed"); \ |
103 | \ |
104 | /*implicit constructor call test*/ \ |
105 | container_type v = INIT_SEQ; \ |
106 | ASSERT(v == expected,"init list constructor failed"); \ |
107 | \ |
108 | /*assignment operator test*/ \ |
109 | /*TODO: count created and destroyed injects to assert that no extra copy of vector was created implicitly*/ \ |
110 | container_type va; \ |
111 | va = INIT_SEQ; \ |
112 | ASSERT(va == expected,"init list operator= failed"); \ |
113 | /*assign(begin,end) test*/ \ |
114 | container_type vae; \ |
115 | vae.assign(INIT_SEQ); \ |
116 | ASSERT(vae == expected,"init list assign(begin,end) failed"); \ |
117 | } \ |
118 | |
119 | namespace initializer_list_helpers{ |
120 | template<typename T> |
121 | class ad_hoc_container{ |
122 | std::vector<T> vec; |
123 | public: |
124 | ad_hoc_container(){} |
125 | typename std::vector<T>::const_iterator begin() const {return vec.begin();} |
126 | typename std::vector<T>::const_iterator end() const {return vec.end();} |
127 | typename std::vector<T>::size_type size() const {return vec.size();} |
128 | template<typename InputIterator> |
129 | ad_hoc_container(InputIterator begin, InputIterator end) : vec(begin,end) {} |
130 | ad_hoc_container(std::initializer_list<T> il) : vec(il.begin(),il.end()) {} |
131 | ad_hoc_container(ad_hoc_container const& other) : vec(other.vec) {} |
132 | ad_hoc_container& operator=(ad_hoc_container const& rhs){ vec=rhs.vec; return *this;} |
133 | ad_hoc_container& operator=(std::initializer_list<T> il){ vec.assign(il.begin(),il.end()); return *this;} |
134 | template<typename InputIterator> |
135 | void assign(InputIterator begin, InputIterator end){ vec.assign(begin,end);} |
136 | void assign(std::initializer_list<T> il){ vec.assign(il.begin(),il.end());} |
137 | friend bool operator==(ad_hoc_container<T> const& lhs, ad_hoc_container<T> const& rhs){ return lhs.vec==rhs.vec;} |
138 | }; |
139 | } |
140 | |
141 | #define AD_HOC_INIT_SEQ {1,2,3,4} |
142 | __TBB_TEST_INIT_LIST_SUITE_SINGLE(TestCompilerSupportInt, initializer_list_helpers::ad_hoc_container, int, AD_HOC_INIT_SEQ ) |
143 | #undef AD_HOC_INIT_SEQ |
144 | |
145 | #if __TBB_CPP11_INIT_LIST_TEST_BROKEN |
146 | void TestCompilerSupportIntPair(){ |
147 | REPORT("Known issue: skip initializer_list compiler test for std::pair list elements.\n" ); |
148 | } |
149 | #else |
150 | #define AD_HOC_PAIR_INIT_SEQ {{1,1}, {2,2},{3,3}, {4,4}} |
151 | #define AD_HOC_INIT_SEQ_PAIR_TYPE std::pair<int,int> |
152 | __TBB_TEST_INIT_LIST_SUITE_SINGLE(TestCompilerSupportIntPair, initializer_list_helpers::ad_hoc_container, AD_HOC_INIT_SEQ_PAIR_TYPE, AD_HOC_PAIR_INIT_SEQ ) |
153 | #undef AD_HOC_INIT_SEQ_PAIR_TYPE |
154 | #undef AD_HOC_PAIR_INIT_SEQ |
155 | #endif |
156 | |
157 | bool TestCompilerForInitializerList(); |
158 | namespace { |
159 | const bool conpiler_init_list_tests_are_run = TestCompilerForInitializerList(); |
160 | } |
161 | |
162 | //TODO: move this to test_compiler |
163 | bool TestCompilerForInitializerList(){ |
164 | TestCompilerSupportInt(); |
165 | TestCompilerSupportIntPair(); |
166 | tbb::internal::suppress_unused_warning(conpiler_init_list_tests_are_run); |
167 | return true; |
168 | } |
169 | } // namespace initializer_list_support_tests |
170 | |
171 | #endif //__TBB_INITIALIZER_LISTS_PRESENT |
172 | #endif //__TBB_test_initializer_list_H |
173 | |