Skip to content

Update tests to new style #963

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 5, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/pybind11/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,8 @@ struct nodelete { template <typename T> void operator()(T*) { } };
NAMESPACE_BEGIN(detail)
template <typename... Args>
struct overload_cast_impl {
constexpr overload_cast_impl() {} // MSVC 2015 needs this

template <typename Return>
constexpr auto operator()(Return (*pf)(Args...)) const noexcept
-> decltype(pf) { return pf; }
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def pytest_namespace():
except ImportError:
scipy = None
try:
from pybind11_tests import have_eigen
from pybind11_tests.eigen import have_eigen
except ImportError:
have_eigen = False
pypy = platform.python_implementation() == "PyPy"
Expand Down
3 changes: 2 additions & 1 deletion tests/pybind11_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ PYBIND11_MODULE(pybind11_tests, m) {
.def(py::init<>())
.def(py::init<int>())
.def("get_value", &UserType::value, "Get value using a method")
.def_property_readonly("value", &UserType::value, "Get value using a property")
.def("set_value", &UserType::set, "Set value using a method")
.def_property("value", &UserType::value, &UserType::set, "Get/set value using a property")
.def("__repr__", [](const UserType& u) { return "UserType({})"_s.format(u.value()); });

py::class_<IncType, UserType>(m, "IncType")
Expand Down
1 change: 1 addition & 0 deletions tests/pybind11_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class UserType {
UserType(int i) : i(i) { }

int value() const { return i; }
void set(int set) { i = set; }

private:
int i = -1;
Expand Down
205 changes: 103 additions & 102 deletions tests/test_buffers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,105 +10,73 @@
#include "pybind11_tests.h"
#include "constructor_stats.h"

class Matrix {
public:
Matrix(ssize_t rows, ssize_t cols) : m_rows(rows), m_cols(cols) {
print_created(this, std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
m_data = new float[(size_t) (rows*cols)];
memset(m_data, 0, sizeof(float) * (size_t) (rows * cols));
}

Matrix(const Matrix &s) : m_rows(s.m_rows), m_cols(s.m_cols) {
print_copy_created(this, std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
m_data = new float[(size_t) (m_rows * m_cols)];
memcpy(m_data, s.m_data, sizeof(float) * (size_t) (m_rows * m_cols));
}

Matrix(Matrix &&s) : m_rows(s.m_rows), m_cols(s.m_cols), m_data(s.m_data) {
print_move_created(this);
s.m_rows = 0;
s.m_cols = 0;
s.m_data = nullptr;
}

~Matrix() {
print_destroyed(this, std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
delete[] m_data;
}

Matrix &operator=(const Matrix &s) {
print_copy_assigned(this, std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
delete[] m_data;
m_rows = s.m_rows;
m_cols = s.m_cols;
m_data = new float[(size_t) (m_rows * m_cols)];
memcpy(m_data, s.m_data, sizeof(float) * (size_t) (m_rows * m_cols));
return *this;
}

Matrix &operator=(Matrix &&s) {
print_move_assigned(this, std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
if (&s != this) {
delete[] m_data;
m_rows = s.m_rows; m_cols = s.m_cols; m_data = s.m_data;
s.m_rows = 0; s.m_cols = 0; s.m_data = nullptr;
TEST_SUBMODULE(buffers, m) {
// test_from_python / test_to_python:
class Matrix {
public:
Matrix(ssize_t rows, ssize_t cols) : m_rows(rows), m_cols(cols) {
print_created(this, std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
m_data = new float[(size_t) (rows*cols)];
memset(m_data, 0, sizeof(float) * (size_t) (rows * cols));
}
return *this;
}

float operator()(ssize_t i, ssize_t j) const {
return m_data[(size_t) (i*m_cols + j)];
}

float &operator()(ssize_t i, ssize_t j) {
return m_data[(size_t) (i*m_cols + j)];
}

float *data() { return m_data; }

ssize_t rows() const { return m_rows; }
ssize_t cols() const { return m_cols; }
private:
ssize_t m_rows;
ssize_t m_cols;
float *m_data;
};

class SquareMatrix : public Matrix {
public:
SquareMatrix(ssize_t n) : Matrix(n, n) { }
};

struct PTMFBuffer {
int32_t value = 0;

py::buffer_info get_buffer_info() {
return py::buffer_info(&value, sizeof(value),
py::format_descriptor<int32_t>::format(), 1);
}
};
Matrix(const Matrix &s) : m_rows(s.m_rows), m_cols(s.m_cols) {
print_copy_created(this, std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
m_data = new float[(size_t) (m_rows * m_cols)];
memcpy(m_data, s.m_data, sizeof(float) * (size_t) (m_rows * m_cols));
}

class ConstPTMFBuffer {
std::unique_ptr<int32_t> value;
Matrix(Matrix &&s) : m_rows(s.m_rows), m_cols(s.m_cols), m_data(s.m_data) {
print_move_created(this);
s.m_rows = 0;
s.m_cols = 0;
s.m_data = nullptr;
}

public:
int32_t get_value() const { return *value; }
void set_value(int32_t v) { *value = v; }
~Matrix() {
print_destroyed(this, std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
delete[] m_data;
}

py::buffer_info get_buffer_info() const {
return py::buffer_info(value.get(), sizeof(*value),
py::format_descriptor<int32_t>::format(), 1);
}
Matrix &operator=(const Matrix &s) {
print_copy_assigned(this, std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
delete[] m_data;
m_rows = s.m_rows;
m_cols = s.m_cols;
m_data = new float[(size_t) (m_rows * m_cols)];
memcpy(m_data, s.m_data, sizeof(float) * (size_t) (m_rows * m_cols));
return *this;
}

ConstPTMFBuffer() : value(new int32_t{0}) { };
};
Matrix &operator=(Matrix &&s) {
print_move_assigned(this, std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
if (&s != this) {
delete[] m_data;
m_rows = s.m_rows; m_cols = s.m_cols; m_data = s.m_data;
s.m_rows = 0; s.m_cols = 0; s.m_data = nullptr;
}
return *this;
}

struct DerivedPTMFBuffer : public PTMFBuffer { };
float operator()(ssize_t i, ssize_t j) const {
return m_data[(size_t) (i*m_cols + j)];
}

test_initializer buffers([](py::module &m) {
py::class_<Matrix> mtx(m, "Matrix", py::buffer_protocol());
float &operator()(ssize_t i, ssize_t j) {
return m_data[(size_t) (i*m_cols + j)];
}

mtx.def(py::init<ssize_t, ssize_t>())
float *data() { return m_data; }

ssize_t rows() const { return m_rows; }
ssize_t cols() const { return m_cols; }
private:
ssize_t m_rows;
ssize_t m_cols;
float *m_data;
};
py::class_<Matrix>(m, "Matrix", py::buffer_protocol())
.def(py::init<ssize_t, ssize_t>())
/// Construct from a buffer
.def("__init__", [](Matrix &v, py::buffer b) {
py::buffer_info info = b.request();
Expand Down Expand Up @@ -143,24 +111,57 @@ test_initializer buffers([](py::module &m) {
})
;


// test_inherited_protocol
class SquareMatrix : public Matrix {
public:
SquareMatrix(ssize_t n) : Matrix(n, n) { }
};
// Derived classes inherit the buffer protocol and the buffer access function
py::class_<SquareMatrix, Matrix>(m, "SquareMatrix")
.def(py::init<ssize_t>());

py::class_<PTMFBuffer>(m, "PTMFBuffer", py::buffer_protocol())

// test_pointer_to_member_fn
// Tests that passing a pointer to member to the base class works in
// the derived class.
struct Buffer {
int32_t value = 0;

py::buffer_info get_buffer_info() {
return py::buffer_info(&value, sizeof(value),
py::format_descriptor<int32_t>::format(), 1);
}
};
py::class_<Buffer>(m, "Buffer", py::buffer_protocol())
.def(py::init<>())
.def_readwrite("value", &PTMFBuffer::value)
.def_buffer(&PTMFBuffer::get_buffer_info);
.def_readwrite("value", &Buffer::value)
.def_buffer(&Buffer::get_buffer_info);


py::class_<ConstPTMFBuffer>(m, "ConstPTMFBuffer", py::buffer_protocol())
class ConstBuffer {
std::unique_ptr<int32_t> value;

public:
int32_t get_value() const { return *value; }
void set_value(int32_t v) { *value = v; }

py::buffer_info get_buffer_info() const {
return py::buffer_info(value.get(), sizeof(*value),
py::format_descriptor<int32_t>::format(), 1);
}

ConstBuffer() : value(new int32_t{0}) { };
};
py::class_<ConstBuffer>(m, "ConstBuffer", py::buffer_protocol())
.def(py::init<>())
.def_property("value", &ConstPTMFBuffer::get_value, &ConstPTMFBuffer::set_value)
.def_buffer(&ConstPTMFBuffer::get_buffer_info);
.def_property("value", &ConstBuffer::get_value, &ConstBuffer::set_value)
.def_buffer(&ConstBuffer::get_buffer_info);

// Tests that passing a pointer to member to the base class works in
// the derived class.
py::class_<DerivedPTMFBuffer>(m, "DerivedPTMFBuffer", py::buffer_protocol())
struct DerivedBuffer : public Buffer { };
py::class_<DerivedBuffer>(m, "DerivedBuffer", py::buffer_protocol())
.def(py::init<>())
.def_readwrite("value", (int32_t DerivedPTMFBuffer::*) &DerivedPTMFBuffer::value)
.def_buffer(&DerivedPTMFBuffer::get_buffer_info);
});
.def_readwrite("value", (int32_t DerivedBuffer::*) &DerivedBuffer::value)
.def_buffer(&DerivedBuffer::get_buffer_info);

}
44 changes: 22 additions & 22 deletions tests/test_buffers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import struct
import pytest
from pybind11_tests import Matrix, ConstructorStats, PTMFBuffer, ConstPTMFBuffer, DerivedPTMFBuffer
from pybind11_tests import buffers as m
from pybind11_tests import ConstructorStats

pytestmark = pytest.requires_numpy

Expand All @@ -10,17 +11,17 @@

def test_from_python():
with pytest.raises(RuntimeError) as excinfo:
Matrix(np.array([1, 2, 3])) # trying to assign a 1D array
m.Matrix(np.array([1, 2, 3])) # trying to assign a 1D array
assert str(excinfo.value) == "Incompatible buffer format!"

m3 = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
m4 = Matrix(m3)
m4 = m.Matrix(m3)

for i in range(m4.rows()):
for j in range(m4.cols()):
assert m3[i, j] == m4[i, j]

cstats = ConstructorStats.get(Matrix)
cstats = ConstructorStats.get(m.Matrix)
assert cstats.alive() == 1
del m3, m4
assert cstats.alive() == 0
Expand All @@ -35,26 +36,26 @@ def test_from_python():
# https://bitbucket.org/pypy/pypy/issues/2444
@pytest.unsupported_on_pypy
def test_to_python():
m = Matrix(5, 5)
assert memoryview(m).shape == (5, 5)
mat = m.Matrix(5, 5)
assert memoryview(mat).shape == (5, 5)

assert m[2, 3] == 0
m[2, 3] = 4
assert m[2, 3] == 4
assert mat[2, 3] == 0
mat[2, 3] = 4
assert mat[2, 3] == 4

m2 = np.array(m, copy=False)
assert m2.shape == (5, 5)
assert abs(m2).sum() == 4
assert m2[2, 3] == 4
m2[2, 3] = 5
assert m2[2, 3] == 5
mat2 = np.array(mat, copy=False)
assert mat2.shape == (5, 5)
assert abs(mat2).sum() == 4
assert mat2[2, 3] == 4
mat2[2, 3] = 5
assert mat2[2, 3] == 5

cstats = ConstructorStats.get(Matrix)
cstats = ConstructorStats.get(m.Matrix)
assert cstats.alive() == 1
del m
del mat
pytest.gc_collect()
assert cstats.alive() == 1
del m2 # holds an m reference
del mat2 # holds a mat reference
pytest.gc_collect()
assert cstats.alive() == 0
assert cstats.values() == ["5x5 matrix"]
Expand All @@ -67,16 +68,15 @@ def test_to_python():
@pytest.unsupported_on_pypy
def test_inherited_protocol():
"""SquareMatrix is derived from Matrix and inherits the buffer protocol"""
from pybind11_tests import SquareMatrix

matrix = SquareMatrix(5)
matrix = m.SquareMatrix(5)
assert memoryview(matrix).shape == (5, 5)
assert np.asarray(matrix).shape == (5, 5)


@pytest.unsupported_on_pypy
def test_ptmf():
for cls in [PTMFBuffer, ConstPTMFBuffer, DerivedPTMFBuffer]:
def test_pointer_to_member_fn():
for cls in [m.Buffer, m.ConstBuffer, m.DerivedBuffer]:
buf = cls()
buf.value = 0x12345678
value = struct.unpack('i', bytearray(buf))[0]
Expand Down
12 changes: 6 additions & 6 deletions tests/test_builtin_casters.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,10 @@ def test_integer_casting():
assert m.i32_str(2000000000) == "2000000000"
assert m.u32_str(2000000000) == "2000000000"
if sys.version_info < (3,):
assert m.i32_str(long(-1)) == "-1"
assert m.i64_str(long(-1)) == "-1"
assert m.i64_str(long(-999999999999)) == "-999999999999"
assert m.u64_str(long(999999999999)) == "999999999999"
assert m.i32_str(long(-1)) == "-1" # noqa: F821 undefined name 'long'
assert m.i64_str(long(-1)) == "-1" # noqa: F821 undefined name 'long'
assert m.i64_str(long(-999999999999)) == "-999999999999" # noqa: F821 undefined name
assert m.u64_str(long(999999999999)) == "999999999999" # noqa: F821 undefined name 'long'
else:
assert m.i64_str(-999999999999) == "-999999999999"
assert m.u64_str(999999999999) == "999999999999"
Expand All @@ -174,10 +174,10 @@ def test_integer_casting():

if sys.version_info < (3,):
with pytest.raises(TypeError) as excinfo:
m.u32_str(long(-1))
m.u32_str(long(-1)) # noqa: F821 undefined name 'long'
assert "incompatible function arguments" in str(excinfo.value)
with pytest.raises(TypeError) as excinfo:
m.u64_str(long(-1))
m.u64_str(long(-1)) # noqa: F821 undefined name 'long'
assert "incompatible function arguments" in str(excinfo.value)


Expand Down
Loading