| 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 | |