Skip to content

Commit 5d3c801

Browse files
committed
tests: extend coverage
1 parent b239797 commit 5d3c801

File tree

1 file changed

+113
-40
lines changed

1 file changed

+113
-40
lines changed

src/buffer.rs

Lines changed: 113 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -570,17 +570,6 @@ impl PyUntypedBuffer {
570570
self.raw().buf
571571
}
572572

573-
/// Returns the Python object that owns the buffer data.
574-
///
575-
/// This is the object that was passed to [`PyBuffer::get()`]
576-
/// when the buffer was created.
577-
/// Calling this before [`release()`][Self::release] and cloning the result
578-
/// allows you to keep the object alive after the buffer is released.
579-
#[inline]
580-
pub fn obj<'py>(&self, py: Python<'py>) -> Option<&Bound<'py, PyAny>> {
581-
unsafe { Bound::ref_from_ptr_or_opt(py, &self.raw().obj).as_ref() }
582-
}
583-
584573
/// Gets a pointer to the specified item.
585574
///
586575
/// If `indices.len() < self.dimensions()`, returns the start address of the sub-array at the specified dimension.
@@ -1288,6 +1277,27 @@ mod tests {
12881277
(c"=d", Float { bytes: 8 }),
12891278
(c"=z", Unknown),
12901279
(c"=0", Unknown),
1280+
// bare char (no prefix) goes to native_element_type_from_type_char
1281+
(
1282+
c"b",
1283+
SignedInteger {
1284+
bytes: size_of::<c_schar>(),
1285+
},
1286+
),
1287+
(
1288+
c"B",
1289+
UnsignedInteger {
1290+
bytes: size_of::<c_uchar>(),
1291+
},
1292+
),
1293+
(c"?", Bool),
1294+
(c"f", Float { bytes: 4 }),
1295+
(c"d", Float { bytes: 8 }),
1296+
(c"z", Unknown),
1297+
// <, >, ! prefixes go to standard_element_type_from_type_char
1298+
(c"<i", SignedInteger { bytes: 4 }),
1299+
(c">H", UnsignedInteger { bytes: 2 }),
1300+
(c"!q", SignedInteger { bytes: 8 }),
12911301
// unknown prefix -> Unknown
12921302
(c":b", Unknown),
12931303
] {
@@ -1325,6 +1335,7 @@ mod tests {
13251335
assert_eq!(slice.len(), 5);
13261336
assert_eq!(slice[0].get(), b'a');
13271337
assert_eq!(slice[2].get(), b'c');
1338+
assert_eq!(unsafe { *slice[0].as_ptr() }, b'a');
13281339

13291340
assert_eq!(unsafe { *(buffer.get_ptr(&[1]).cast::<u8>()) }, b'b');
13301341

@@ -1398,47 +1409,67 @@ mod tests {
13981409
});
13991410
}
14001411

1412+
#[test]
1413+
fn test_copy_to_fortran_slice() {
1414+
Python::attach(|py| {
1415+
let array = py
1416+
.import("array")
1417+
.unwrap()
1418+
.call_method("array", ("f", (1.0, 1.5, 2.0, 2.5)), None)
1419+
.unwrap();
1420+
let buffer = PyBuffer::get(&array).unwrap();
1421+
1422+
// wrong length
1423+
assert!(buffer.copy_to_fortran_slice(py, &mut [0.0f32]).is_err());
1424+
// correct length
1425+
let mut arr = [0.0f32; 4];
1426+
buffer.copy_to_fortran_slice(py, &mut arr).unwrap();
1427+
assert_eq!(arr, [1.0, 1.5, 2.0, 2.5]);
1428+
});
1429+
}
1430+
1431+
#[test]
1432+
fn test_copy_from_slice_wrong_length() {
1433+
Python::attach(|py| {
1434+
let array = py
1435+
.import("array")
1436+
.unwrap()
1437+
.call_method("array", ("f", (1.0, 1.5, 2.0, 2.5)), None)
1438+
.unwrap();
1439+
let buffer = PyBuffer::get(&array).unwrap();
1440+
// writable buffer, but wrong length
1441+
assert!(!buffer.readonly());
1442+
assert!(buffer.copy_from_slice(py, &[0.0f32; 2]).is_err());
1443+
assert!(buffer.copy_from_fortran_slice(py, &[0.0f32; 2]).is_err());
1444+
});
1445+
}
1446+
14011447
#[test]
14021448
fn test_untyped_buffer() {
14031449
Python::attach(|py| {
14041450
let bytes = PyBytes::new(py, b"abcde");
1405-
let untyped = PyUntypedBuffer::get(&bytes).unwrap();
1406-
assert_eq!(untyped.dimensions(), 1);
1407-
assert_eq!(untyped.item_count(), 5);
1408-
assert_eq!(untyped.format().to_str().unwrap(), "B");
1409-
assert_eq!(untyped.shape(), [5]);
1451+
let buffer = PyUntypedBuffer::get(&bytes).unwrap();
1452+
assert_eq!(buffer.dimensions(), 1);
1453+
assert_eq!(buffer.item_count(), 5);
1454+
assert_eq!(buffer.format().to_str().unwrap(), "B");
1455+
assert_eq!(buffer.shape(), [5]);
1456+
assert!(!buffer.buf_ptr().is_null());
1457+
assert_eq!(buffer.strides(), &[1]);
1458+
assert_eq!(buffer.len_bytes(), 5);
1459+
assert_eq!(buffer.item_size(), 1);
1460+
assert!(buffer.readonly());
1461+
assert!(buffer.suboffsets().is_none());
14101462

1411-
let typed: &PyBuffer<u8> = untyped.as_typed().unwrap();
1463+
assert!(format!("{:?}", buffer).starts_with("PyUntypedBuffer { buf: "));
1464+
1465+
let typed: &PyBuffer<u8> = buffer.as_typed().unwrap();
14121466
assert_eq!(typed.dimensions(), 1);
14131467
assert_eq!(typed.item_count(), 5);
14141468
assert_eq!(typed.format().to_str().unwrap(), "B");
14151469
assert_eq!(typed.shape(), [5]);
14161470
});
14171471
}
14181472

1419-
#[test]
1420-
fn test_obj_getter() {
1421-
Python::attach(|py| {
1422-
let bytes = PyBytes::new(py, b"hello");
1423-
let buf = PyUntypedBuffer::get(bytes.as_any()).unwrap();
1424-
1425-
// obj() returns the same object that owns the buffer
1426-
let owner = buf.obj(py).unwrap();
1427-
assert!(owner.is_instance_of::<PyBytes>());
1428-
assert!(owner.is(&bytes));
1429-
1430-
// can keep the owner alive after releasing the buffer
1431-
let owner_ref: crate::Py<PyAny> = owner.clone().unbind();
1432-
buf.release(py);
1433-
drop(bytes);
1434-
// owner_ref still valid after buffer and original are dropped
1435-
Python::attach(|py| {
1436-
let rebound = owner_ref.bind(py);
1437-
assert!(rebound.is_instance_of::<PyBytes>());
1438-
});
1439-
});
1440-
}
1441-
14421473
#[test]
14431474
fn test_untyped_buffer_view() {
14441475
Python::attach(|py| {
@@ -1536,6 +1567,48 @@ mod tests {
15361567
});
15371568
}
15381569

1570+
#[test]
1571+
fn test_typed_buffer_view_with_flags() {
1572+
Python::attach(|py| {
1573+
let array = py
1574+
.import("array")
1575+
.unwrap()
1576+
.call_method("array", ("f", (1.0, 1.5, 2.0, 2.5)), None)
1577+
.unwrap();
1578+
1579+
PyBufferView::<f32, Known, Unknown, Unknown>::with_flags(
1580+
&array,
1581+
ffi::PyBUF_ND,
1582+
|view| {
1583+
assert_eq!(view.item_count(), 4);
1584+
assert_eq!(view.format().to_str().unwrap(), "f");
1585+
1586+
let slice = view.as_slice(py).unwrap();
1587+
assert_eq!(slice[0].get(), 1.0);
1588+
assert_eq!(slice[3].get(), 2.5);
1589+
1590+
let mut_slice = view.as_mut_slice(py).unwrap();
1591+
mut_slice[0].set(9.0);
1592+
assert_eq!(slice[0].get(), 9.0);
1593+
},
1594+
)
1595+
.unwrap();
1596+
});
1597+
}
1598+
1599+
#[test]
1600+
fn test_typed_buffer_view_with_flags_incompatible() {
1601+
Python::attach(|py| {
1602+
let bytes = PyBytes::new(py, b"abcde");
1603+
let result = PyBufferView::<f32, Known, Unknown, Unknown>::with_flags(
1604+
&bytes,
1605+
ffi::PyBUF_ND,
1606+
|_view| {},
1607+
);
1608+
assert!(result.is_err());
1609+
});
1610+
}
1611+
15391612
#[test]
15401613
fn test_buffer_view_error() {
15411614
Python::attach(|py| {

0 commit comments

Comments
 (0)