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