this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include <cstring>
3
4#include "Python.h"
5#include "gtest/gtest.h"
6
7#include "capi-fixture.h"
8#include "capi-testing.h"
9
10namespace py {
11namespace testing {
12
13using MemoryViewExtensionApiTest = ExtensionApi;
14
15TEST_F(MemoryViewExtensionApiTest, FromObjectWithNoneRaisesTypeError) {
16 PyObjectPtr result(PyMemoryView_FromObject(Py_None));
17 ASSERT_EQ(result, nullptr);
18 ASSERT_NE(PyErr_Occurred(), nullptr);
19 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
20}
21
22TEST_F(MemoryViewExtensionApiTest, FromObjectWithBytesReturnsMemoryView) {
23 PyObjectPtr bytes(PyBytes_FromString(""));
24 PyObjectPtr result(PyMemoryView_FromObject(bytes));
25 EXPECT_EQ(PyErr_Occurred(), nullptr);
26 EXPECT_TRUE(PyMemoryView_Check(result));
27}
28
29TEST_F(MemoryViewExtensionApiTest, FromObjectWithMemoryViewReturnsMemoryView) {
30 PyObjectPtr bytes(PyBytes_FromString(""));
31 PyObjectPtr view(PyMemoryView_FromObject(bytes));
32 ASSERT_TRUE(PyMemoryView_Check(view));
33 PyObjectPtr result(PyMemoryView_FromObject(view));
34 EXPECT_EQ(PyErr_Occurred(), nullptr);
35 EXPECT_TRUE(PyMemoryView_Check(result));
36 EXPECT_NE(result.get(), view.get());
37}
38
39TEST_F(MemoryViewExtensionApiTest,
40 FromObjectWithBufferProtocolReturnsMemoryView) {
41 static char contents[] = "hello world";
42 static Py_ssize_t contents_len = std::strlen(contents);
43 getbufferproc getbuffer_func = [](PyObject* obj, Py_buffer* view, int flags) {
44 return PyBuffer_FillInfo(view, obj, ::strdup(contents), contents_len,
45 /*readonly=*/1, flags);
46 };
47 releasebufferproc releasebuffer_func = [](PyObject*, Py_buffer* view) {
48 std::free(view->buf);
49 view->obj = nullptr;
50 };
51 PyType_Slot slots[] = {
52 {Py_bf_getbuffer, reinterpret_cast<void*>(getbuffer_func)},
53 {Py_bf_releasebuffer, reinterpret_cast<void*>(releasebuffer_func)},
54 {0, nullptr},
55 };
56 static PyType_Spec spec;
57 spec = {
58 "foo.Bar", 0, 0, Py_TPFLAGS_DEFAULT, slots,
59 };
60 PyObjectPtr type(PyType_FromSpec(&spec));
61 ASSERT_NE(type, nullptr);
62 PyObjectPtr instance(PyObject_CallFunction(type, nullptr));
63 ASSERT_NE(instance, nullptr);
64 PyObjectPtr view(PyMemoryView_FromObject(instance));
65 ASSERT_NE(view, nullptr);
66 EXPECT_EQ(PyErr_Occurred(), nullptr);
67 EXPECT_TRUE(PyMemoryView_Check(view));
68}
69
70TEST_F(MemoryViewExtensionApiTest,
71 DunderNewWithBufferProtocolReturnsMemoryView) {
72 static char contents[] = "hello world";
73 static Py_ssize_t contents_len = std::strlen(contents);
74 getbufferproc getbuffer_func = [](PyObject* obj, Py_buffer* view, int flags) {
75 return PyBuffer_FillInfo(view, obj, ::strdup(contents), contents_len,
76 /*readonly=*/1, flags);
77 };
78 releasebufferproc releasebuffer_func = [](PyObject*, Py_buffer* view) {
79 std::free(view->buf);
80 view->obj = nullptr;
81 };
82 PyType_Slot slots[] = {
83 {Py_bf_getbuffer, reinterpret_cast<void*>(getbuffer_func)},
84 {Py_bf_releasebuffer, reinterpret_cast<void*>(releasebuffer_func)},
85 {0, nullptr},
86 };
87 static PyType_Spec spec;
88 spec = {
89 "foo.Bar", 0, 0, Py_TPFLAGS_DEFAULT, slots,
90 };
91 PyObjectPtr type(PyType_FromSpec(&spec));
92 ASSERT_NE(type, nullptr);
93 PyObjectPtr instance(PyObject_CallFunction(type, nullptr));
94 ASSERT_NE(instance, nullptr);
95 PyObjectPtr view(PyObject_CallFunction(
96 reinterpret_cast<PyObject*>(&PyMemoryView_Type), "O", instance.get()));
97 ASSERT_NE(view, nullptr);
98 EXPECT_EQ(PyErr_Occurred(), nullptr);
99 EXPECT_TRUE(PyMemoryView_Check(view));
100}
101
102TEST_F(MemoryViewExtensionApiTest, FromMemoryReturnsMemoryView) {
103 const int size = 5;
104 int memory[size] = {0};
105 PyObjectPtr result(PyMemoryView_FromMemory(reinterpret_cast<char*>(memory),
106 size, PyBUF_READ));
107 EXPECT_NE(result, nullptr);
108 EXPECT_EQ(PyErr_Occurred(), nullptr);
109 EXPECT_TRUE(PyMemoryView_Check(result));
110}
111
112} // namespace testing
113} // namespace py