this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "Python.h"
3#include "gtest/gtest.h"
4
5#include "capi-fixture.h"
6#include "capi-testing.h"
7
8namespace py {
9namespace testing {
10
11using SliceExtensionApiTest = ExtensionApi;
12
13TEST_F(SliceExtensionApiTest, NewReturnsSlice) {
14 PyObjectPtr slice(PySlice_New(nullptr, nullptr, nullptr));
15 EXPECT_TRUE(PySlice_Check(slice));
16}
17
18TEST_F(SliceExtensionApiTest, AdjustIndicesReturnsSliceLength) {
19 Py_ssize_t length = 10;
20 Py_ssize_t start = 2;
21 Py_ssize_t stop = -1;
22 Py_ssize_t step = 3;
23 Py_ssize_t slice_length = PySlice_AdjustIndices(length, &start, &stop, step);
24 EXPECT_EQ(slice_length, 3);
25 EXPECT_EQ(start, 2);
26 EXPECT_EQ(stop, 9);
27}
28
29TEST_F(SliceExtensionApiTest, AdjustIndicesWithNegativeShifts) {
30 Py_ssize_t length = 5;
31 Py_ssize_t start = -4;
32 Py_ssize_t stop = -1;
33 Py_ssize_t step = 1;
34 Py_ssize_t slice_length = PySlice_AdjustIndices(length, &start, &stop, step);
35 EXPECT_EQ(slice_length, 3);
36 EXPECT_EQ(start, 1);
37 EXPECT_EQ(stop, 4);
38}
39
40TEST_F(SliceExtensionApiTest,
41 AdjustIndicesWithLargeNegativesAndPositiveStepSetsZero) {
42 Py_ssize_t length = 5;
43 Py_ssize_t start = -40;
44 Py_ssize_t stop = -10;
45 Py_ssize_t step = 2;
46 Py_ssize_t slice_length = PySlice_AdjustIndices(length, &start, &stop, step);
47 EXPECT_EQ(slice_length, 0);
48 EXPECT_EQ(start, 0);
49 EXPECT_EQ(stop, 0);
50}
51
52TEST_F(SliceExtensionApiTest,
53 AdjustIndicesWithLargeNegativesAndNegativeStepSetsNegativeOne) {
54 Py_ssize_t length = 5;
55 Py_ssize_t start = -40;
56 Py_ssize_t stop = -100;
57 Py_ssize_t step = -2;
58 Py_ssize_t slice_length = PySlice_AdjustIndices(length, &start, &stop, step);
59 EXPECT_EQ(slice_length, 0);
60 EXPECT_EQ(start, -1);
61 EXPECT_EQ(stop, -1);
62}
63
64TEST_F(SliceExtensionApiTest, AdjustIndicesWithLargeIndicesSetsLength) {
65 Py_ssize_t length = 5;
66 Py_ssize_t start = 8;
67 Py_ssize_t stop = 10;
68 Py_ssize_t step = 1;
69 Py_ssize_t slice_length = PySlice_AdjustIndices(length, &start, &stop, step);
70 EXPECT_EQ(slice_length, 0);
71 EXPECT_EQ(start, 5);
72 EXPECT_EQ(stop, 5);
73}
74
75TEST_F(SliceExtensionApiTest,
76 AdjustIndicesWithLargeIndicesAndNegativeStepSetsOffsetLength) {
77 Py_ssize_t length = 5;
78 Py_ssize_t start = 8;
79 Py_ssize_t stop = 10;
80 Py_ssize_t step = -1;
81 Py_ssize_t slice_length = PySlice_AdjustIndices(length, &start, &stop, step);
82 EXPECT_EQ(slice_length, 0);
83 EXPECT_EQ(start, 4);
84 EXPECT_EQ(stop, 4);
85}
86
87TEST_F(SliceExtensionApiTest, GetIndicesExWithUnpackErrorRaisesValueError) {
88 PyObjectPtr zero(PyLong_FromLong(0));
89 PyObjectPtr slice(PySlice_New(nullptr, nullptr, zero));
90 Py_ssize_t length = 0;
91 Py_ssize_t start, stop, step, slicelength;
92 int result =
93 PySlice_GetIndicesEx(slice, length, &start, &stop, &step, &slicelength);
94 ASSERT_EQ(result, -1);
95 ASSERT_NE(PyErr_Occurred(), nullptr);
96 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError));
97}
98
99TEST_F(SliceExtensionApiTest, GetIndicesExWithUnpackSuccessSetsValues) {
100 PyObjectPtr two(PyLong_FromLong(2));
101 PyObjectPtr slice(PySlice_New(nullptr, nullptr, two));
102 Py_ssize_t length = 10;
103 Py_ssize_t start, stop, step, slicelength;
104 int result =
105 PySlice_GetIndicesEx(slice, length, &start, &stop, &step, &slicelength);
106 ASSERT_EQ(result, 0);
107 ASSERT_EQ(PyErr_Occurred(), nullptr);
108 EXPECT_EQ(start, 0);
109 EXPECT_EQ(stop, 10);
110 EXPECT_EQ(step, 2);
111 EXPECT_EQ(slicelength, 5);
112}
113
114TEST_F(SliceExtensionApiTest, UnpackWithNonSliceRaisesSystemErrorPyro) {
115 PyObjectPtr num(PyLong_FromLong(0));
116 Py_ssize_t start, stop, step;
117 ASSERT_EQ(PySlice_Unpack(num, &start, &stop, &step), -1);
118 ASSERT_NE(PyErr_Occurred(), nullptr);
119 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
120}
121
122TEST_F(SliceExtensionApiTest, UnpackWithNonIndexStartRaisesTypeError) {
123 PyObjectPtr list(PyList_New(0));
124 PyObjectPtr slice(PySlice_New(list, nullptr, nullptr));
125 Py_ssize_t start, stop, step;
126 ASSERT_EQ(PySlice_Unpack(slice, &start, &stop, &step), -1);
127 ASSERT_NE(PyErr_Occurred(), nullptr);
128 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
129}
130
131TEST_F(SliceExtensionApiTest, UnpackWithNonIndexStopRaisesTypeError) {
132 PyObjectPtr list(PyList_New(0));
133 PyObjectPtr slice(PySlice_New(nullptr, list, nullptr));
134 Py_ssize_t start, stop, step;
135 ASSERT_EQ(PySlice_Unpack(slice, &start, &stop, &step), -1);
136 ASSERT_NE(PyErr_Occurred(), nullptr);
137 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
138}
139
140TEST_F(SliceExtensionApiTest, UnpackWithNonIndexStepRaisesTypeError) {
141 PyObjectPtr list(PyList_New(0));
142 PyObjectPtr slice(PySlice_New(nullptr, nullptr, list));
143 Py_ssize_t start, stop, step;
144 ASSERT_EQ(PySlice_Unpack(slice, &start, &stop, &step), -1);
145 ASSERT_NE(PyErr_Occurred(), nullptr);
146 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
147}
148
149TEST_F(SliceExtensionApiTest, UnpackWithZeroStepRaisesTypeError) {
150 PyObjectPtr zero(PyLong_FromLong(0));
151 PyObjectPtr slice(PySlice_New(nullptr, nullptr, zero));
152 Py_ssize_t start, stop, step;
153 ASSERT_EQ(PySlice_Unpack(slice, &start, &stop, &step), -1);
154 ASSERT_NE(PyErr_Occurred(), nullptr);
155 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError));
156}
157
158TEST_F(SliceExtensionApiTest, UnpackWithNoneSetsDefaults) {
159 PyObjectPtr slice(PySlice_New(nullptr, nullptr, nullptr));
160 Py_ssize_t start, stop, step;
161 ASSERT_EQ(PySlice_Unpack(slice, &start, &stop, &step), 0);
162 ASSERT_EQ(PyErr_Occurred(), nullptr);
163 EXPECT_EQ(start, 0);
164 EXPECT_GT(stop, 1 << 30); // Arbitrary large value less than
165 // PY_SSIZE_T_MAX and SmallInt::kMaxValue
166 EXPECT_EQ(step, 1);
167}
168
169TEST_F(SliceExtensionApiTest, UnpackWithNonIntCallsDunderIndex) {
170 PyRun_SimpleString(R"(
171class Foo:
172 def __init__(self): self.bar = 0
173 def __index__(self):
174 self.bar += 1
175 return self.bar
176foo = Foo()
177)");
178 PyObjectPtr foo(mainModuleGet("foo"));
179 PyObjectPtr slice(PySlice_New(foo, foo, foo));
180 Py_ssize_t start, stop, step;
181 ASSERT_EQ(PySlice_Unpack(slice, &start, &stop, &step), 0);
182 ASSERT_EQ(PyErr_Occurred(), nullptr);
183 EXPECT_EQ(start, 2);
184 EXPECT_EQ(stop, 3);
185 EXPECT_EQ(step, 1);
186}
187
188TEST_F(SliceExtensionApiTest, UnpackWithIndicesSetsValues) {
189 PyObjectPtr idx1(PyLong_FromLong(1024));
190 PyObjectPtr idx2(PyLong_FromLong(-42));
191 PyObjectPtr idx3(PyLong_FromLong(10));
192 PyObjectPtr slice(PySlice_New(idx1, idx2, idx3));
193 Py_ssize_t start, stop, step;
194 ASSERT_EQ(PySlice_Unpack(slice, &start, &stop, &step), 0);
195 ASSERT_EQ(PyErr_Occurred(), nullptr);
196 EXPECT_EQ(start, 1024);
197 EXPECT_GE(stop, -42);
198 EXPECT_EQ(step, 10);
199}
200
201} // namespace testing
202} // namespace py