| /* |
| * Copyright 2019-2021 Hans-Kristian Arntzen |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "spirv_cross.hpp" |
| #include <memory> |
| |
| using namespace spirv_cross; |
| |
| // Test the tricky bits of the implementation. |
| // Running the entire test suite on this implementation should find all other potential issues. |
| |
| static int allocations = 0; |
| static int deallocations = 0; |
| |
| #define SPVC_ASSERT(x) do { \ |
| if (!(x)) SPIRV_CROSS_THROW("Assert: " #x " failed!"); \ |
| } while(0) |
| |
| struct RAIIInt |
| { |
| RAIIInt(int v_) : v(v_) { allocations++; } |
| ~RAIIInt() { deallocations++; } |
| RAIIInt() { allocations++; } |
| RAIIInt(const RAIIInt &other) { v = other.v; allocations++; } |
| RAIIInt(RAIIInt &&other) SPIRV_CROSS_NOEXCEPT { v = other.v; allocations++; } |
| RAIIInt &operator=(RAIIInt &&) = default; |
| RAIIInt &operator=(const RAIIInt &) = default; |
| |
| int v = 0; |
| }; |
| |
| static void propagate_stack_to_heap() |
| { |
| SmallVector<RAIIInt, 2> ints; |
| ints.emplace_back(1); |
| ints.emplace_back(2); |
| auto *old_data = ints.data(); |
| SPVC_ASSERT(ints[0].v == 1); |
| SPVC_ASSERT(ints[1].v == 2); |
| ints.emplace_back(3); |
| SPVC_ASSERT(old_data != ints.data()); |
| SPVC_ASSERT(ints[0].v == 1); |
| SPVC_ASSERT(ints[1].v == 2); |
| SPVC_ASSERT(ints[2].v == 3); |
| SPVC_ASSERT(ints.size() == 3); |
| } |
| |
| static void insert_end() |
| { |
| SmallVector<RAIIInt, 2> ints; |
| ints.emplace_back(1); |
| ints.emplace_back(2); |
| |
| const RAIIInt new_ints[3] = { 10, 20, 30 }; |
| ints.insert(ints.end(), new_ints, new_ints + 3); |
| SPVC_ASSERT(ints.size() == 5); |
| |
| SPVC_ASSERT(ints[0].v == 1); |
| SPVC_ASSERT(ints[1].v == 2); |
| SPVC_ASSERT(ints[2].v == 10); |
| SPVC_ASSERT(ints[3].v == 20); |
| SPVC_ASSERT(ints[4].v == 30); |
| } |
| |
| static void insert_begin_realloc() |
| { |
| SmallVector<RAIIInt, 2> ints; |
| ints.emplace_back(1); |
| ints.emplace_back(2); |
| |
| const RAIIInt new_ints[3] = { 10, 20, 30 }; |
| ints.insert(ints.begin(), new_ints, new_ints + 3); |
| SPVC_ASSERT(ints.size() == 5); |
| |
| SPVC_ASSERT(ints[0].v == 10); |
| SPVC_ASSERT(ints[1].v == 20); |
| SPVC_ASSERT(ints[2].v == 30); |
| SPVC_ASSERT(ints[3].v == 1); |
| SPVC_ASSERT(ints[4].v == 2); |
| } |
| |
| static void insert_middle_realloc() |
| { |
| SmallVector<RAIIInt, 2> ints; |
| ints.emplace_back(1); |
| ints.emplace_back(2); |
| |
| const RAIIInt new_ints[3] = { 10, 20, 30 }; |
| ints.insert(ints.begin() + 1, new_ints, new_ints + 3); |
| SPVC_ASSERT(ints.size() == 5); |
| |
| SPVC_ASSERT(ints[0].v == 1); |
| SPVC_ASSERT(ints[1].v == 10); |
| SPVC_ASSERT(ints[2].v == 20); |
| SPVC_ASSERT(ints[3].v == 30); |
| SPVC_ASSERT(ints[4].v == 2); |
| } |
| |
| static void insert_begin_no_realloc() |
| { |
| SmallVector<RAIIInt, 2> ints; |
| ints.reserve(10); |
| ints.emplace_back(1); |
| ints.emplace_back(2); |
| |
| const RAIIInt new_ints[3] = { 10, 20, 30 }; |
| ints.insert(ints.begin(), new_ints, new_ints + 3); |
| SPVC_ASSERT(ints.size() == 5); |
| |
| SPVC_ASSERT(ints[0].v == 10); |
| SPVC_ASSERT(ints[1].v == 20); |
| SPVC_ASSERT(ints[2].v == 30); |
| SPVC_ASSERT(ints[3].v == 1); |
| SPVC_ASSERT(ints[4].v == 2); |
| } |
| |
| static void insert_middle_no_realloc() |
| { |
| SmallVector<RAIIInt, 2> ints; |
| ints.reserve(10); |
| ints.emplace_back(1); |
| ints.emplace_back(2); |
| |
| const RAIIInt new_ints[3] = { 10, 20, 30 }; |
| ints.insert(ints.begin() + 1, new_ints, new_ints + 3); |
| SPVC_ASSERT(ints.size() == 5); |
| |
| SPVC_ASSERT(ints[0].v == 1); |
| SPVC_ASSERT(ints[1].v == 10); |
| SPVC_ASSERT(ints[2].v == 20); |
| SPVC_ASSERT(ints[3].v == 30); |
| SPVC_ASSERT(ints[4].v == 2); |
| } |
| |
| static void erase_end() |
| { |
| SmallVector<RAIIInt, 2> ints; |
| ints.emplace_back(1); |
| ints.emplace_back(2); |
| ints.emplace_back(3); |
| ints.emplace_back(4); |
| ints.erase(ints.begin() + 1, ints.end()); |
| |
| SPVC_ASSERT(ints.size() == 1); |
| SPVC_ASSERT(ints[0].v == 1); |
| } |
| |
| static void erase_middle() |
| { |
| SmallVector<RAIIInt, 2> ints; |
| ints.emplace_back(1); |
| ints.emplace_back(2); |
| ints.emplace_back(3); |
| ints.emplace_back(4); |
| ints.erase(ints.begin() + 1, ints.end() - 1); |
| |
| SPVC_ASSERT(ints.size() == 2); |
| SPVC_ASSERT(ints[0].v == 1); |
| SPVC_ASSERT(ints[1].v == 4); |
| } |
| |
| static void erase_start() |
| { |
| SmallVector<RAIIInt, 2> ints; |
| ints.emplace_back(1); |
| ints.emplace_back(2); |
| ints.emplace_back(3); |
| ints.emplace_back(4); |
| ints.erase(ints.begin(), ints.end() - 2); |
| |
| SPVC_ASSERT(ints.size() == 2); |
| SPVC_ASSERT(ints[0].v == 3); |
| SPVC_ASSERT(ints[1].v == 4); |
| } |
| |
| static void convert_to_std_vector() |
| { |
| SmallVector<RAIIInt, 4> foo; |
| foo.push_back(1); |
| foo.push_back(2); |
| std::vector<RAIIInt> ints(foo); |
| SPVC_ASSERT(ints.size() == 2); |
| SPVC_ASSERT(foo.size() == 2); |
| SPVC_ASSERT(ints[0].v == 1); |
| SPVC_ASSERT(ints[1].v == 2); |
| |
| // This doesn't work on MSVC 2013. Ignore it. |
| #if !(defined(_MSC_VER) && _MSC_VER < 1900) |
| SmallVector<std::unique_ptr<RAIIInt>> move_only_buffer; |
| move_only_buffer.emplace_back(new RAIIInt(40)); |
| std::vector<std::unique_ptr<RAIIInt>> move_only_vector(std::move(move_only_buffer)); |
| SPVC_ASSERT(move_only_vector.size() == 1); |
| SPVC_ASSERT(move_only_vector[0]->v == 40); |
| #endif |
| } |
| |
| int main() |
| { |
| propagate_stack_to_heap(); |
| insert_end(); |
| insert_begin_realloc(); |
| insert_begin_no_realloc(); |
| insert_middle_realloc(); |
| insert_middle_no_realloc(); |
| erase_end(); |
| erase_middle(); |
| erase_start(); |
| |
| convert_to_std_vector(); |
| |
| SPVC_ASSERT(allocations > 0 && deallocations > 0 && deallocations == allocations); |
| } |
| |