1 /*
2 * Copyright 2019 Hans-Kristian Arntzen
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 #include "spirv_cross.hpp"
18 #include <memory>
19
20 using namespace spirv_cross;
21
22 // Test the tricky bits of the implementation.
23 // Running the entire test suite on this implementation should find all other potential issues.
24
25 static int allocations = 0;
26 static int deallocations = 0;
27
28 #define SPVC_ASSERT(x) do { \
29 if (!(x)) SPIRV_CROSS_THROW("Assert: " #x " failed!"); \
30 } while(0)
31
32 struct RAIIInt
33 {
RAIIIntRAIIInt34 RAIIInt(int v_) : v(v_) { allocations++; }
~RAIIIntRAIIInt35 ~RAIIInt() { deallocations++; }
RAIIIntRAIIInt36 RAIIInt() { allocations++; }
RAIIIntRAIIInt37 RAIIInt(const RAIIInt &other) { v = other.v; allocations++; }
RAIIIntRAIIInt38 RAIIInt(RAIIInt &&other) SPIRV_CROSS_NOEXCEPT { v = other.v; allocations++; }
39 RAIIInt &operator=(RAIIInt &&) = default;
40 RAIIInt &operator=(const RAIIInt &) = default;
41
42 int v = 0;
43 };
44
propagate_stack_to_heap()45 static void propagate_stack_to_heap()
46 {
47 SmallVector<RAIIInt, 2> ints;
48 ints.emplace_back(1);
49 ints.emplace_back(2);
50 auto *old_data = ints.data();
51 SPVC_ASSERT(ints[0].v == 1);
52 SPVC_ASSERT(ints[1].v == 2);
53 ints.emplace_back(3);
54 SPVC_ASSERT(old_data != ints.data());
55 SPVC_ASSERT(ints[0].v == 1);
56 SPVC_ASSERT(ints[1].v == 2);
57 SPVC_ASSERT(ints[2].v == 3);
58 SPVC_ASSERT(ints.size() == 3);
59 }
60
insert_end()61 static void insert_end()
62 {
63 SmallVector<RAIIInt, 2> ints;
64 ints.emplace_back(1);
65 ints.emplace_back(2);
66
67 const RAIIInt new_ints[3] = { 10, 20, 30 };
68 ints.insert(ints.end(), new_ints, new_ints + 3);
69 SPVC_ASSERT(ints.size() == 5);
70
71 SPVC_ASSERT(ints[0].v == 1);
72 SPVC_ASSERT(ints[1].v == 2);
73 SPVC_ASSERT(ints[2].v == 10);
74 SPVC_ASSERT(ints[3].v == 20);
75 SPVC_ASSERT(ints[4].v == 30);
76 }
77
insert_begin_realloc()78 static void insert_begin_realloc()
79 {
80 SmallVector<RAIIInt, 2> ints;
81 ints.emplace_back(1);
82 ints.emplace_back(2);
83
84 const RAIIInt new_ints[3] = { 10, 20, 30 };
85 ints.insert(ints.begin(), new_ints, new_ints + 3);
86 SPVC_ASSERT(ints.size() == 5);
87
88 SPVC_ASSERT(ints[0].v == 10);
89 SPVC_ASSERT(ints[1].v == 20);
90 SPVC_ASSERT(ints[2].v == 30);
91 SPVC_ASSERT(ints[3].v == 1);
92 SPVC_ASSERT(ints[4].v == 2);
93 }
94
insert_middle_realloc()95 static void insert_middle_realloc()
96 {
97 SmallVector<RAIIInt, 2> ints;
98 ints.emplace_back(1);
99 ints.emplace_back(2);
100
101 const RAIIInt new_ints[3] = { 10, 20, 30 };
102 ints.insert(ints.begin() + 1, new_ints, new_ints + 3);
103 SPVC_ASSERT(ints.size() == 5);
104
105 SPVC_ASSERT(ints[0].v == 1);
106 SPVC_ASSERT(ints[1].v == 10);
107 SPVC_ASSERT(ints[2].v == 20);
108 SPVC_ASSERT(ints[3].v == 30);
109 SPVC_ASSERT(ints[4].v == 2);
110 }
111
insert_begin_no_realloc()112 static void insert_begin_no_realloc()
113 {
114 SmallVector<RAIIInt, 2> ints;
115 ints.reserve(10);
116 ints.emplace_back(1);
117 ints.emplace_back(2);
118
119 const RAIIInt new_ints[3] = { 10, 20, 30 };
120 ints.insert(ints.begin(), new_ints, new_ints + 3);
121 SPVC_ASSERT(ints.size() == 5);
122
123 SPVC_ASSERT(ints[0].v == 10);
124 SPVC_ASSERT(ints[1].v == 20);
125 SPVC_ASSERT(ints[2].v == 30);
126 SPVC_ASSERT(ints[3].v == 1);
127 SPVC_ASSERT(ints[4].v == 2);
128 }
129
insert_middle_no_realloc()130 static void insert_middle_no_realloc()
131 {
132 SmallVector<RAIIInt, 2> ints;
133 ints.reserve(10);
134 ints.emplace_back(1);
135 ints.emplace_back(2);
136
137 const RAIIInt new_ints[3] = { 10, 20, 30 };
138 ints.insert(ints.begin() + 1, new_ints, new_ints + 3);
139 SPVC_ASSERT(ints.size() == 5);
140
141 SPVC_ASSERT(ints[0].v == 1);
142 SPVC_ASSERT(ints[1].v == 10);
143 SPVC_ASSERT(ints[2].v == 20);
144 SPVC_ASSERT(ints[3].v == 30);
145 SPVC_ASSERT(ints[4].v == 2);
146 }
147
erase_end()148 static void erase_end()
149 {
150 SmallVector<RAIIInt, 2> ints;
151 ints.emplace_back(1);
152 ints.emplace_back(2);
153 ints.emplace_back(3);
154 ints.emplace_back(4);
155 ints.erase(ints.begin() + 1, ints.end());
156
157 SPVC_ASSERT(ints.size() == 1);
158 SPVC_ASSERT(ints[0].v == 1);
159 }
160
erase_middle()161 static void erase_middle()
162 {
163 SmallVector<RAIIInt, 2> ints;
164 ints.emplace_back(1);
165 ints.emplace_back(2);
166 ints.emplace_back(3);
167 ints.emplace_back(4);
168 ints.erase(ints.begin() + 1, ints.end() - 1);
169
170 SPVC_ASSERT(ints.size() == 2);
171 SPVC_ASSERT(ints[0].v == 1);
172 SPVC_ASSERT(ints[1].v == 4);
173 }
174
erase_start()175 static void erase_start()
176 {
177 SmallVector<RAIIInt, 2> ints;
178 ints.emplace_back(1);
179 ints.emplace_back(2);
180 ints.emplace_back(3);
181 ints.emplace_back(4);
182 ints.erase(ints.begin(), ints.end() - 2);
183
184 SPVC_ASSERT(ints.size() == 2);
185 SPVC_ASSERT(ints[0].v == 3);
186 SPVC_ASSERT(ints[1].v == 4);
187 }
188
convert_to_std_vector()189 static void convert_to_std_vector()
190 {
191 SmallVector<RAIIInt, 4> foo;
192 foo.push_back(1);
193 foo.push_back(2);
194 std::vector<RAIIInt> ints(foo);
195 SPVC_ASSERT(ints.size() == 2);
196 SPVC_ASSERT(foo.size() == 2);
197 SPVC_ASSERT(ints[0].v == 1);
198 SPVC_ASSERT(ints[1].v == 2);
199
200 // This doesn't work on MSVC 2013. Ignore it.
201 #if !(defined(_MSC_VER) && _MSC_VER < 1900)
202 SmallVector<std::unique_ptr<RAIIInt>> move_only_buffer;
203 move_only_buffer.emplace_back(new RAIIInt(40));
204 std::vector<std::unique_ptr<RAIIInt>> move_only_vector(std::move(move_only_buffer));
205 SPVC_ASSERT(move_only_vector.size() == 1);
206 SPVC_ASSERT(move_only_vector[0]->v == 40);
207 #endif
208 }
209
main()210 int main()
211 {
212 propagate_stack_to_heap();
213 insert_end();
214 insert_begin_realloc();
215 insert_begin_no_realloc();
216 insert_middle_realloc();
217 insert_middle_no_realloc();
218 erase_end();
219 erase_middle();
220 erase_start();
221
222 convert_to_std_vector();
223
224 SPVC_ASSERT(allocations > 0 && deallocations > 0 && deallocations == allocations);
225 }
226
227