/***************************************************************************
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
* Copyright (c) QuantStack *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#include "xtensor/containers/xbuffer_adaptor.hpp"
#include "test_common_macros.hpp"
namespace xt
{
using buffer_adaptor = xbuffer_adaptor;
using allocator = std::allocator;
using owner_adaptor = xbuffer_adaptor;
TEST(xbuffer_adaptor, owner_destructor)
{
size_t size = 100;
double* data = allocator{}.allocate(size);
owner_adaptor adapt(data, size);
EXPECT_EQ(data, adapt.data());
}
TEST(xbuffer_adaptor, owner_move)
{
size_t size = 100;
double* data = allocator{}.allocate(size);
owner_adaptor adapt(data, size);
owner_adaptor adapt2(std::move(adapt));
EXPECT_EQ(data, adapt2.data());
EXPECT_EQ(size, adapt2.size());
EXPECT_EQ(size_t(0), adapt.size());
}
TEST(xbuffer_adaptor, owner_copy_assign)
{
size_t size1 = 100;
double* data1 = allocator{}.allocate(size1);
data1[0] = 2.5;
owner_adaptor adapt1(data1, size1);
size_t size2 = 200;
double* data2 = allocator{}.allocate(size2);
data2[0] = 1.2;
owner_adaptor adapt2(data2, size2);
adapt1 = adapt2;
EXPECT_EQ(adapt1.size(), adapt2.size());
EXPECT_EQ(adapt1[0], adapt2[0]);
}
TEST(xbuffer_adaptor, owner_move_assign)
{
size_t size1 = 100;
double* data1 = allocator{}.allocate(size1);
data1[0] = 2.5;
owner_adaptor adapt1(data1, size1);
size_t size2 = 200;
double* data2 = allocator{}.allocate(size2);
double data2_ref = 1.2;
data2[0] = data2_ref;
owner_adaptor adapt2(data2, size2);
adapt1 = std::move(adapt2);
EXPECT_EQ(adapt1.size(), size2);
EXPECT_EQ(adapt1[0], data2_ref);
}
class size_check_allocator : public std::allocator
{
public:
size_t* allocate(size_t n)
{
size_t* res = std::allocator::allocate(n);
// store the size into the result so we can
// check if the size is correct when we deallocate.
res[0] = n;
return res;
}
void deallocate(size_t* p, size_t n)
{
EXPECT_EQ(p[0], n);
return std::allocator::deallocate(p, n);
}
};
TEST(xbuffer_adaptor, owner_move_assign_check_size)
{
size_check_allocator custom_allocator;
using owner_adaptor = xbuffer_adaptor;
size_t size1 = 100;
size_t* data1 = custom_allocator.allocate(size1);
owner_adaptor adapt1(data1, size1);
size_t size2 = 200;
size_t* data2 = custom_allocator.allocate(size2);
owner_adaptor adapt2(data2, size2);
adapt1 = adapt2;
EXPECT_EQ(adapt1.size(), size2);
}
TEST(xbuffer_adaptor, owner_resize)
{
size_t size1 = 100;
double* data1 = allocator{}.allocate(size1);
owner_adaptor adapt(data1, size1);
size_t size2 = 50;
adapt.resize(size2);
EXPECT_EQ(adapt.size(), size2);
}
TEST(xbuffer_adaptor, owner_iterating)
{
size_t size = 100;
double* data = allocator{}.allocate(size);
owner_adaptor adapt(data, size);
std::fill(adapt.begin(), adapt.end(), 1.2);
EXPECT_EQ(data[0], 1.2);
EXPECT_EQ(data[size / 2], 1.2);
EXPECT_EQ(data[size - 1], 1.2);
}
TEST(xbuffer_adaptor, no_owner_copy)
{
size_t size = 100;
double* data = new double[size];
buffer_adaptor adapt1(data, size);
buffer_adaptor adapt2(adapt1);
EXPECT_EQ(adapt1.size(), adapt2.size());
EXPECT_EQ(adapt1.data(), adapt2.data());
delete[] data;
}
TEST(xbuffer_adaptor, no_owner_move)
{
size_t size = 100;
double* data = new double[size];
buffer_adaptor adapt1(data, size);
buffer_adaptor adapt2(std::move(adapt1));
EXPECT_EQ(adapt1.size(), adapt2.size());
EXPECT_EQ(adapt1.data(), adapt2.data());
delete[] data;
}
TEST(xbuffer_adaptor, no_owner_copy_assign)
{
size_t size1 = 100;
double* data1 = new double[size1];
buffer_adaptor adapt1(data1, size1);
size_t size2 = 200;
double* data2 = new double[size2];
buffer_adaptor adapt2(data2, size2);
adapt1 = adapt2;
EXPECT_EQ(adapt1.size(), adapt2.size());
EXPECT_EQ(adapt1.data(), adapt2.data());
delete[] data2;
delete[] data1;
}
TEST(xbuffer_adaptor, no_owner_move_assign)
{
size_t size1 = 100;
double* data1 = new double[size1];
buffer_adaptor adapt1(data1, size1);
size_t size2 = 200;
double* data2 = new double[size2];
buffer_adaptor adapt2(data2, size2);
adapt1 = std::move(adapt2);
EXPECT_EQ(adapt1.size(), adapt2.size());
EXPECT_EQ(adapt1.data(), adapt2.data());
delete[] data2;
delete[] data1;
}
TEST(xbuffer_adaptor, no_owner_resize)
{
size_t size1 = 100;
double* data1 = new double[size1];
buffer_adaptor adapt(data1, size1);
size_t size2 = 50;
XT_EXPECT_THROW(adapt.resize(size2), std::runtime_error);
EXPECT_EQ(adapt.size(), size1);
delete[] data1;
}
TEST(xbuffer_adaptor, no_owner_iterating)
{
size_t size = 100;
double* data = new double[size];
buffer_adaptor adapt(data, size);
std::fill(adapt.begin(), adapt.end(), 1.2);
EXPECT_EQ(data[0], 1.2);
EXPECT_EQ(data[size / 2], 1.2);
EXPECT_EQ(data[size - 1], 1.2);
delete[] data;
}
}