blob: e9a3bb0bee4ace015d68e6ac6b0fa6486f08e4be [file] [log] [blame]
/*
* 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);
}