this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "range-builtins.h"
3
4#include "gtest/gtest.h"
5
6#include "builtins.h"
7#include "frame.h"
8#include "objects.h"
9#include "runtime.h"
10#include "test-utils.h"
11
12namespace py {
13namespace testing {
14
15using LongRangeIteratorBuiltinsTest = RuntimeFixture;
16using RangeBuiltinsTest = RuntimeFixture;
17using RangeIteratorBuiltinsTest = RuntimeFixture;
18
19TEST_F(LongRangeIteratorBuiltinsTest, DunderIterReturnsSelf) {
20 HandleScope scope(thread_);
21 Int start(&scope, SmallInt::fromWord(0));
22 Int stop(&scope, runtime_->newIntFromUnsigned(kMaxUword));
23 Int step(&scope, SmallInt::fromWord(1));
24 Object iter(&scope, runtime_->newLongRangeIterator(start, stop, step));
25 Object result(&scope, runBuiltin(METH(longrange_iterator, __iter__), iter));
26 EXPECT_EQ(result, iter);
27}
28
29TEST_F(LongRangeIteratorBuiltinsTest, DunderLengthHintReturnsPendingLength) {
30 HandleScope scope(thread_);
31 Int zero(&scope, SmallInt::fromWord(0));
32 Int six(&scope, SmallInt::fromWord(6));
33 Int neg(&scope, SmallInt::fromWord(-6));
34 Int max(&scope, runtime_->newIntFromUnsigned(kMaxUword));
35 Object empty(&scope, runtime_->newLongRangeIterator(max, zero, six));
36 Object forwards(&scope, runtime_->newLongRangeIterator(zero, max, six));
37 Object backwards(&scope, runtime_->newLongRangeIterator(max, zero, neg));
38 word expected = static_cast<word>(kMaxUword / 6 + 1);
39
40 Object length_hint1(
41 &scope, runBuiltin(METH(longrange_iterator, __length_hint__), empty));
42 EXPECT_TRUE(isIntEqualsWord(*length_hint1, 0));
43
44 Object length_hint2(
45 &scope, runBuiltin(METH(longrange_iterator, __length_hint__), forwards));
46 EXPECT_TRUE(isIntEqualsWord(*length_hint2, expected));
47
48 Object length_hint3(
49 &scope, runBuiltin(METH(longrange_iterator, __length_hint__), backwards));
50 EXPECT_TRUE(isIntEqualsWord(*length_hint3, expected));
51}
52
53TEST_F(LongRangeIteratorBuiltinsTest, DunderNextWithEmptyRaisesStopIteration) {
54 HandleScope scope(thread_);
55 Int start(&scope, runtime_->newIntFromUnsigned(kMaxUword));
56 Int stop(&scope, SmallInt::fromWord(0));
57 Int step(&scope, SmallInt::fromWord(1));
58 Object iter(&scope, runtime_->newLongRangeIterator(start, stop, step));
59 EXPECT_TRUE(raised(runBuiltin(METH(longrange_iterator, __next__), iter),
60 LayoutId::kStopIteration));
61}
62
63TEST_F(LongRangeIteratorBuiltinsTest, DunderNextWithNonEmptyReturnsInts) {
64 HandleScope scope(thread_);
65 Int start(&scope, runtime_->newIntFromUnsigned(kMaxUword - 15));
66 Int stop(&scope, runtime_->newIntFromUnsigned(kMaxUword));
67 Int step(&scope, SmallInt::fromWord(10));
68 Object iter(&scope, runtime_->newLongRangeIterator(start, stop, step));
69
70 Object item1(&scope, runBuiltin(METH(longrange_iterator, __next__), iter));
71 const uword result1[] = {kMaxUword - 15, 0};
72 EXPECT_TRUE(isIntEqualsDigits(*item1, result1));
73
74 Object item2(&scope, runBuiltin(METH(longrange_iterator, __next__), iter));
75 const uword result2[] = {kMaxUword - 5, 0};
76 EXPECT_TRUE(isIntEqualsDigits(*item2, result2));
77
78 EXPECT_TRUE(raised(runBuiltin(METH(longrange_iterator, __next__), iter),
79 LayoutId::kStopIteration));
80}
81
82TEST_F(LongRangeIteratorBuiltinsTest, DunderNextModifiesPendingLength) {
83 HandleScope scope(thread_);
84 Int start(&scope, SmallInt::fromWord(0));
85 Int stop(&scope, runtime_->newIntFromUnsigned(kMaxUword));
86 Int step(&scope, SmallInt::fromWord(4));
87 LongRangeIterator iter(&scope,
88 runtime_->newLongRangeIterator(start, stop, step));
89 Object length_hint(
90 &scope, runBuiltin(METH(longrange_iterator, __length_hint__), iter));
91 word result1 = static_cast<word>(kMaxUword / 4 + 1);
92 EXPECT_TRUE(isIntEqualsWord(*length_hint, result1));
93
94 ASSERT_FALSE(runBuiltin(METH(longrange_iterator, __next__), iter).isError());
95 length_hint = runBuiltin(METH(longrange_iterator, __length_hint__), iter);
96 word result2 = result1 - 1;
97 EXPECT_TRUE(isIntEqualsWord(*length_hint, result2));
98}
99
100TEST_F(RangeBuiltinsTest, DunderIterReturnsRangeIter) {
101 HandleScope scope(thread_);
102 Int zero(&scope, SmallInt::fromWord(0));
103 Int one(&scope, SmallInt::fromWord(1));
104 Object range(&scope, runtime_->newRange(zero, one, one));
105 Object iter(&scope, runBuiltin(METH(range, __iter__), range));
106 EXPECT_TRUE(iter.isRangeIterator());
107}
108
109TEST_F(RangeBuiltinsTest, DunderLenWithNonRangeRaisesTypeError) {
110 HandleScope scope(thread_);
111 Object not_range(&scope, runtime_->emptySlice());
112 ASSERT_TRUE(raised(runBuiltin(METH(range, __len__), not_range),
113 LayoutId::kTypeError));
114}
115
116TEST_F(RangeBuiltinsTest, DunderLenWithForwardRangeReturnsSliceLength) {
117 HandleScope scope(thread_);
118 Int start(&scope, SmallInt::fromWord(-4));
119 Int stop(&scope, SmallInt::fromWord(13));
120 Int step(&scope, SmallInt::fromWord(5));
121 Object empty(&scope, runtime_->newRange(stop, start, step));
122 Object range(&scope, runtime_->newRange(start, stop, step));
123 Object len1(&scope, runBuiltin(METH(range, __len__), empty));
124 Object len2(&scope, runBuiltin(METH(range, __len__), range));
125 EXPECT_TRUE(isIntEqualsWord(*len1, 0));
126 EXPECT_TRUE(isIntEqualsWord(*len2, 4));
127}
128
129TEST_F(RangeBuiltinsTest, DunderLenWithBackwardRangeReturnsSliceLength) {
130 HandleScope scope(thread_);
131 Int start(&scope, SmallInt::fromWord(15));
132 Int stop(&scope, SmallInt::fromWord(3));
133 Int step(&scope, SmallInt::fromWord(-2));
134 Object empty(&scope, runtime_->newRange(stop, start, step));
135 Object range(&scope, runtime_->newRange(start, stop, step));
136 Object len1(&scope, runBuiltin(METH(range, __len__), empty));
137 Object len2(&scope, runBuiltin(METH(range, __len__), range));
138 EXPECT_TRUE(isIntEqualsWord(*len1, 0));
139 EXPECT_TRUE(isIntEqualsWord(*len2, 6));
140}
141
142TEST_F(RangeBuiltinsTest, DunderLenWithLargeIntReturnsLength) {
143 HandleScope scope(thread_);
144 Int start(&scope, SmallInt::fromWord(0));
145 Int stop(&scope, runtime_->newIntFromUnsigned(kMaxUword));
146 Int step(&scope, SmallInt::fromWord(10));
147 word expected = static_cast<word>(kMaxUword / 10 + 1);
148 Object range(&scope, runtime_->newRange(start, stop, step));
149 Object len(&scope, runBuiltin(METH(range, __len__), range));
150 EXPECT_TRUE(isIntEqualsWord(*len, expected));
151}
152
153TEST_F(RangeIteratorBuiltinsTest, DunderIterReturnsSelf) {
154 HandleScope scope(thread_);
155 Object iter(&scope, runtime_->newRangeIterator(0, 2, 13));
156 Object result(&scope, runBuiltin(METH(range_iterator, __iter__), iter));
157 EXPECT_EQ(result, iter);
158}
159
160TEST_F(RangeIteratorBuiltinsTest, DunderLengthHintReturnsPendingLength) {
161 HandleScope scope(thread_);
162 Object empty(&scope, runtime_->newRangeIterator(-12, 10, 0));
163 Object forwards(&scope, runtime_->newRangeIterator(3, 15, 4));
164 Object backwards(&scope, runtime_->newRangeIterator(0, -3, 2));
165
166 Object length_hint1(&scope,
167 runBuiltin(METH(range_iterator, __length_hint__), empty));
168 EXPECT_TRUE(isIntEqualsWord(*length_hint1, 0));
169
170 Object length_hint2(
171 &scope, runBuiltin(METH(range_iterator, __length_hint__), forwards));
172 EXPECT_TRUE(isIntEqualsWord(*length_hint2, 4));
173
174 Object length_hint3(
175 &scope, runBuiltin(METH(range_iterator, __length_hint__), backwards));
176 EXPECT_TRUE(isIntEqualsWord(*length_hint3, 2));
177}
178
179TEST_F(RangeIteratorBuiltinsTest, DunderNextWithEmptyRaisesStopIteration) {
180 HandleScope scope(thread_);
181 Object iter(&scope, runtime_->newRangeIterator(23, 5, 0));
182 EXPECT_TRUE(raised(runBuiltin(METH(range_iterator, __next__), iter),
183 LayoutId::kStopIteration));
184}
185
186TEST_F(RangeIteratorBuiltinsTest, DunderNextWithNonEmptyReturnsInts) {
187 HandleScope scope(thread_);
188 Object iter(&scope, runtime_->newRangeIterator(0, 1, 2));
189
190 Object item1(&scope, runBuiltin(METH(range_iterator, __next__), iter));
191 EXPECT_TRUE(isIntEqualsWord(*item1, 0));
192
193 Object item2(&scope, runBuiltin(METH(range_iterator, __next__), iter));
194 EXPECT_TRUE(isIntEqualsWord(*item2, 1));
195
196 EXPECT_TRUE(raised(runBuiltin(METH(range_iterator, __next__), iter),
197 LayoutId::kStopIteration));
198}
199
200TEST_F(RangeIteratorBuiltinsTest, DunderNextModifiesPendingLength) {
201 HandleScope scope(thread_);
202 RangeIterator iter(&scope, runtime_->newRangeIterator(0, 1, 2));
203
204 ASSERT_FALSE(runBuiltin(METH(range_iterator, __next__), iter).isError());
205 Object length_hint(&scope,
206 runBuiltin(METH(range_iterator, __length_hint__), iter));
207 EXPECT_TRUE(isIntEqualsWord(*length_hint, 1));
208
209 ASSERT_FALSE(runBuiltin(METH(range_iterator, __next__), iter).isError());
210 length_hint = runBuiltin(METH(range_iterator, __length_hint__), iter);
211 EXPECT_TRUE(isIntEqualsWord(*length_hint, 0));
212}
213
214} // namespace testing
215} // namespace py