this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include <cstdint>
3
4#include "gtest/gtest.h"
5
6#include "byteslike.h"
7#include "runtime.h"
8#include "str-builtins.h"
9#include "test-utils.h"
10
11namespace py {
12namespace testing {
13
14using BytearrayTest = RuntimeFixture;
15using LargeBytesTest = RuntimeFixture;
16using SmallBytesTest = RuntimeFixture;
17using CodeTest = RuntimeFixture;
18using ComplexTest = RuntimeFixture;
19using DequeTest = RuntimeFixture;
20using DoubleTest = RuntimeFixture;
21using IntTest = RuntimeFixture;
22using LargeStrTest = RuntimeFixture;
23using ListTest = RuntimeFixture;
24using MmapTest = RuntimeFixture;
25using ModulesTest = RuntimeFixture;
26using MutableBytesTest = RuntimeFixture;
27using MutableTupleTest = RuntimeFixture;
28using SliceTest = RuntimeFixture;
29using SmallStrTest = RuntimeFixture;
30using StrArrayTest = RuntimeFixture;
31using StrTest = RuntimeFixture;
32using StringTest = RuntimeFixture;
33using ValueCellTest = RuntimeFixture;
34using WeakRefTest = RuntimeFixture;
35
36TEST_F(BytearrayTest, DownsizeMaintainsCapacity) {
37 HandleScope scope(thread_);
38 Bytearray array(&scope, runtime_->newBytearray());
39 const byte byte_array[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
40 runtime_->bytearrayExtend(thread_, array, byte_array);
41 ASSERT_EQ(array.numItems(), 9);
42 word capacity = array.capacity();
43 array.downsize(5);
44 EXPECT_EQ(array.numItems(), 5);
45 EXPECT_EQ(array.capacity(), capacity);
46}
47
48TEST_F(DequeTest, DequeClearRemovesElements) {
49 HandleScope scope(thread_);
50 Deque self(&scope, runtime_->newDeque());
51 MutableTuple underlying_tuple(&scope, runtime_->newMutableTuple(5));
52 underlying_tuple.atPut(0, SmallInt::fromWord(0));
53 underlying_tuple.atPut(1, SmallInt::fromWord(1));
54 underlying_tuple.atPut(2, SmallInt::fromWord(2));
55
56 self.setItems(*underlying_tuple);
57 self.setNumItems(3);
58 self.clear();
59 ASSERT_EQ(self.numItems(), 0);
60 ASSERT_EQ(self.left(), 0);
61 EXPECT_EQ(self.at(0), NoneType::object());
62 EXPECT_EQ(self.at(1), NoneType::object());
63 EXPECT_EQ(self.at(2), NoneType::object());
64}
65
66TEST_F(SmallBytesTest, CopyToStartAtCopiesToDestinationStartingAtIndex) {
67 byte src_bytes[] = "hello";
68 HandleScope scope(thread_);
69 Bytes src(&scope, runtime_->newBytesWithAll(src_bytes));
70 byte result[5] = {0};
71 src.copyToStartAt(result, 4, 1);
72 EXPECT_STREQ(reinterpret_cast<char*>(result), "ello");
73}
74
75TEST_F(SmallBytesTest, FindByteWithZeroLengthReturnsNegativeOne) {
76 byte src_bytes[] = "hello";
77 HandleScope scope(thread_);
78 SmallBytes bytes(&scope, runtime_->newBytesWithAll(src_bytes));
79 EXPECT_EQ(bytes.findByte('h', 0, 0), -1);
80}
81
82TEST_F(SmallBytesTest, FindByteWithEndBeforeByteReturnsNegativeOne) {
83 byte src_bytes[] = "hello";
84 HandleScope scope(thread_);
85 SmallBytes bytes(&scope, runtime_->newBytesWithAll(src_bytes));
86 EXPECT_EQ(bytes.findByte('o', 1, 2), -1);
87}
88
89TEST_F(SmallBytesTest, FindByteWithByteNotInBytesReturnsNegativeOne) {
90 byte src_bytes[] = "hello";
91 HandleScope scope(thread_);
92 SmallBytes bytes(&scope, runtime_->newBytesWithAll(src_bytes));
93 EXPECT_EQ(bytes.findByte('x', 0, bytes.length()), -1);
94}
95
96TEST_F(SmallBytesTest, FindByteWithByteInBytesReturnsIndex) {
97 byte src_bytes[] = "hello";
98 HandleScope scope(thread_);
99 SmallBytes bytes(&scope, runtime_->newBytesWithAll(src_bytes));
100 EXPECT_EQ(bytes.findByte('o', 0, bytes.length()), 4);
101}
102
103TEST_F(LargeBytesTest, FindByteWithZerolengthReturnsNegativeOne) {
104 byte src_bytes[] = "hello world this is patrick";
105 HandleScope scope(thread_);
106 LargeBytes bytes(&scope, runtime_->newBytesWithAll(src_bytes));
107 EXPECT_EQ(bytes.findByte('h', 0, 0), -1);
108}
109
110TEST_F(LargeBytesTest, FindByteWithEndBeforeByteReturnsNegativeOne) {
111 byte src_bytes[] = "hello world";
112 HandleScope scope(thread_);
113 LargeBytes bytes(&scope, runtime_->newBytesWithAll(src_bytes));
114 EXPECT_EQ(bytes.findByte('d', 3, 5), -1);
115}
116
117TEST_F(LargeBytesTest, FindByteWithByteNotInBytesReturnsNegativeOne) {
118 byte src_bytes[] = "hello world";
119 HandleScope scope(thread_);
120 LargeBytes bytes(&scope, runtime_->newBytesWithAll(src_bytes));
121 EXPECT_EQ(bytes.findByte('x', 0, bytes.length()), -1);
122}
123
124TEST_F(LargeBytesTest, FindByteWithByteInBytesReturnsIndex) {
125 byte src_bytes[] = "hello world";
126 HandleScope scope(thread_);
127 LargeBytes bytes(&scope, runtime_->newBytesWithAll(src_bytes));
128 EXPECT_EQ(bytes.findByte('o', 0, bytes.length()), 4);
129}
130
131TEST_F(LargeBytesTest, FindByteNonZeroStartReturnsIndex) {
132 byte src_bytes[] = "hello world";
133 HandleScope scope(thread_);
134 LargeBytes bytes(&scope, runtime_->newBytesWithAll(src_bytes));
135 EXPECT_EQ(bytes.findByte('o', 5, bytes.length() - 5), 7);
136}
137
138TEST_F(LargeBytesTest, CopyToStartAtCopiesToDestinationStartingAtIndex) {
139 byte src_bytes[] = "hello world this is patrick";
140 HandleScope scope(thread_);
141 LargeBytes src(&scope, runtime_->newBytesWithAll(src_bytes));
142 byte result[8] = {0};
143 src.copyToStartAt(result, 7, 20);
144 EXPECT_STREQ(reinterpret_cast<char*>(result), "patrick");
145}
146
147TEST_F(MutableBytesTest,
148 IndexOfAnyWithDifferentStartReturnsFirstMatchIndexAfterStart) {
149 HandleScope scope(thread_);
150
151 const byte src_bytes[] = {'h', 'e', 'l', 'l', 'o', ' ',
152 'w', 'o', 'r', 'l', 'd'};
153 word src_length = ARRAYSIZE(src_bytes);
154 MutableBytes src(&scope, runtime_->newMutableBytesUninitialized(src_length));
155 for (word i = 0; i < src_length; i++) {
156 src.byteAtPut(i, src_bytes[i]);
157 }
158 const byte needle[] = "eor";
159 EXPECT_EQ(src.indexOfAny(needle, 0), 1);
160 EXPECT_EQ(src.indexOfAny(needle, 2), 4);
161 EXPECT_EQ(src.indexOfAny(needle, 5), 7);
162}
163
164TEST_F(MutableBytesTest, IndexOfAnyWithNeedleNoMatchReturnsHaystackLength) {
165 HandleScope scope(thread_);
166
167 const byte src_bytes[] = {'h', 'e', 'l', 'l', 'o', ' ',
168 'w', 'o', 'r', 'l', 'd'};
169 word src_length = ARRAYSIZE(src_bytes);
170 MutableBytes src(&scope, runtime_->newMutableBytesUninitialized(src_length));
171 for (word i = 0; i < src_length; i++) {
172 src.byteAtPut(i, src_bytes[i]);
173 }
174 const byte needle[] = "abc";
175 EXPECT_EQ(src.indexOfAny(needle, 0), src_length);
176 EXPECT_EQ(src.indexOfAny(needle, 5), src_length);
177 EXPECT_EQ(src.indexOfAny(needle, 9), src_length);
178}
179
180TEST_F(MutableBytesTest, ReplaceFromWithByteslikeReplacesBytes) {
181 HandleScope scope(thread_);
182 const byte bytes[] = "hello world";
183 Object value(&scope, runtime_->newBytesWithAll(bytes));
184 Byteslike byteslike(&scope, thread_, *value);
185 ASSERT_TRUE(byteslike.isValid());
186 MutableBytes mutable_bytes(&scope,
187 runtime_->newMutableBytesUninitialized(11));
188 mutable_bytes.replaceFromWithByteslike(0, byteslike, 5);
189 mutable_bytes.replaceFromWithByteslike(5, byteslike, 2);
190 mutable_bytes.replaceFromWithByteslike(11, byteslike, 0);
191 mutable_bytes.replaceFromWithByteslike(7, byteslike, 3);
192 mutable_bytes.byteAtPut(10, '\0');
193 const byte expected[] = "hellohehel";
194 EXPECT_TRUE(isMutableBytesEqualsBytes(mutable_bytes, expected));
195}
196
197TEST_F(MutableBytesTest, ReplaceFromWithByteslikeStartAtReplacesBytes) {
198 HandleScope scope(thread_);
199 const byte bytes[] = "hello world";
200 Object value(&scope, runtime_->newBytesWithAll(bytes));
201 Byteslike byteslike(&scope, thread_, *value);
202 ASSERT_TRUE(byteslike.isValid());
203 MutableBytes mutable_bytes(&scope,
204 runtime_->newMutableBytesUninitialized(10));
205 mutable_bytes.replaceFromWithByteslikeStartAt(0, byteslike, 5, 0);
206 mutable_bytes.replaceFromWithByteslikeStartAt(2, byteslike, 4, 1);
207 mutable_bytes.replaceFromWithByteslikeStartAt(6, byteslike, 4, 8);
208 mutable_bytes.replaceFromWithByteslikeStartAt(7, byteslike, 0, 11);
209 mutable_bytes.replaceFromWithByteslikeStartAt(10, byteslike, 0, 0);
210 const byte expected[] = "heellorld";
211 EXPECT_TRUE(isMutableBytesEqualsBytes(mutable_bytes, expected));
212}
213
214TEST_F(MutableBytesTest, ReplaceFromWithStartAtSelfNoop) {
215 HandleScope scope(thread_);
216 const byte src_bytes[] = "patrick";
217 word src_length = ARRAYSIZE(src_bytes);
218 MutableBytes src(&scope, runtime_->newMutableBytesUninitialized(src_length));
219 for (word i = 0; i < src_length; i++) {
220 src.byteAtPut(i, src_bytes[i]);
221 }
222 ASSERT_TRUE(isMutableBytesEqualsBytes(src, src_bytes));
223 src.replaceFromWithStartAt(0, *src, 3, 0);
224 EXPECT_TRUE(isMutableBytesEqualsBytes(src, src_bytes));
225}
226
227TEST_F(MutableBytesTest, ReplaceFromWithStartAtSelfBackward) {
228 HandleScope scope(thread_);
229 const byte src_bytes[] = "patrick";
230 word src_length = ARRAYSIZE(src_bytes);
231 MutableBytes src(&scope, runtime_->newMutableBytesUninitialized(src_length));
232 for (word i = 0; i < src_length; i++) {
233 src.byteAtPut(i, src_bytes[i]);
234 }
235 ASSERT_TRUE(isMutableBytesEqualsBytes(src, src_bytes));
236 src.replaceFromWithStartAt(0, *src, 3, 4);
237 const byte expected[] = "ickrick";
238 EXPECT_TRUE(isMutableBytesEqualsBytes(src, expected));
239}
240
241TEST_F(MutableBytesTest, ReplaceFromWithStartAtSelfForward) {
242 HandleScope scope(thread_);
243 const byte src_bytes[] = "patrick";
244 word src_length = ARRAYSIZE(src_bytes);
245 MutableBytes src(&scope, runtime_->newMutableBytesUninitialized(src_length));
246 for (word i = 0; i < src_length; i++) {
247 src.byteAtPut(i, src_bytes[i]);
248 }
249 ASSERT_TRUE(isMutableBytesEqualsBytes(src, src_bytes));
250 src.replaceFromWithStartAt(4, *src, 3, 0);
251 const byte expected[] = "patrpat";
252 EXPECT_TRUE(isMutableBytesEqualsBytes(src, expected));
253}
254
255TEST_F(MutableBytesTest, ReplaceFromWithStartAtReplacesStartingAtSrcIndex) {
256 byte src_bytes[] = "hello world this is patrick";
257 HandleScope scope(thread_);
258 LargeBytes src(&scope, runtime_->newBytesWithAll(src_bytes));
259 MutableBytes dst(&scope, runtime_->newMutableBytesUninitialized(8));
260 dst.replaceFromWithStartAt(0, *src, 7, 20);
261 const byte expected[] = "patrick";
262 EXPECT_TRUE(isMutableBytesEqualsBytes(dst, expected));
263}
264
265TEST_F(CodeTest, OffsetToLineNumReturnsLineNumber) {
266 const char* src = R"(
267def func():
268 a = 1
269 b = 2
270 print(a, b)
271)";
272 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
273 HandleScope scope(thread_);
274
275 // The bytecode for func is roughly:
276 // LOAD_CONST # a = 1
277 // STORE_FAST
278 //
279 // LOAD_CONST # b = 2
280 // STORE_FAST
281 //
282 // LOAD_GLOBAL # print(a, b)
283 // LOAD_FAST
284 // LOAD_FAST
285 // CALL_FUNCTION
286
287 Function func(&scope, mainModuleAt(runtime_, "func"));
288 Code code(&scope, func.code());
289 ASSERT_EQ(code.firstlineno(), 2);
290
291 // a = 1
292 EXPECT_EQ(code.offsetToLineNum(0), 3);
293 EXPECT_EQ(code.offsetToLineNum(2 * kCodeUnitScale), 3);
294
295 // b = 2
296 EXPECT_EQ(code.offsetToLineNum(4 * kCodeUnitScale), 4);
297 EXPECT_EQ(code.offsetToLineNum(6 * kCodeUnitScale), 4);
298
299 // print(a, b)
300 for (word i = 8; i < Bytes::cast(code.code()).length(); i++) {
301 EXPECT_EQ(code.offsetToLineNum(i * kCodeUnitScale), 5);
302 }
303}
304
305TEST_F(DoubleTest, DoubleTest) {
306 RawObject o = runtime_->newFloat(3.14);
307 ASSERT_TRUE(o.isFloat());
308 RawFloat d = Float::cast(o);
309 EXPECT_EQ(d.value(), 3.14);
310}
311
312TEST_F(ComplexTest, ComplexTest) {
313 RawObject o = runtime_->newComplex(1.0, 2.0);
314 ASSERT_TRUE(o.isComplex());
315 RawComplex c = Complex::cast(o);
316 EXPECT_EQ(c.real(), 1.0);
317 EXPECT_EQ(c.imag(), 2.0);
318}
319
320TEST_F(IntTest, IntTest) {
321 HandleScope scope(thread_);
322
323 Object o1(&scope, runtime_->newInt(42));
324 EXPECT_TRUE(isIntEqualsWord(*o1, 42));
325
326 Object o2(&scope, runtime_->newInt(9223372036854775807L));
327 EXPECT_TRUE(isIntEqualsWord(*o2, 9223372036854775807L));
328
329 int stack_val = 123;
330 Int o3(&scope, runtime_->newIntFromCPtr(&stack_val));
331 EXPECT_EQ(*static_cast<int*>(o3.asCPtr()), 123);
332
333 Object o4(&scope, runtime_->newInt(kMinWord));
334 EXPECT_TRUE(isIntEqualsWord(*o4, kMinWord));
335
336 uword digits[] = {kMaxUword, 0};
337 Int o5(&scope, runtime_->newLargeIntWithDigits(digits));
338 EXPECT_TRUE(o5.isLargeInt());
339 EXPECT_EQ(o5.bitLength(), kBitsPerWord);
340
341 uword digits2[] = {kMaxUword, 1};
342 Int o6(&scope, runtime_->newLargeIntWithDigits(digits2));
343 EXPECT_TRUE(o6.isLargeInt());
344 EXPECT_EQ(o6.bitLength(), kBitsPerWord + 1);
345}
346
347TEST_F(IntTest, LargeIntValid) {
348 HandleScope scope(thread_);
349
350 uword digits[] = {static_cast<uword>(-1234), static_cast<uword>(-1)};
351 LargeInt i(&scope, newLargeIntWithDigits(digits));
352 // Redundant sign-extension
353 EXPECT_FALSE(i.isValid());
354
355 i.digitAtPut(1, -2);
356 EXPECT_TRUE(i.isValid());
357
358 i.digitAtPut(0, 1234);
359 i.digitAtPut(1, 0);
360 // Redundant zero-extension
361 EXPECT_FALSE(i.isValid());
362
363 i.digitAtPut(1, 1);
364 EXPECT_TRUE(i.isValid());
365}
366
367TEST_F(IntTest, IsPositive) {
368 HandleScope scope(thread_);
369
370 Int zero(&scope, runtime_->newInt(0));
371 EXPECT_FALSE(zero.isPositive());
372
373 Int one(&scope, runtime_->newInt(1));
374 EXPECT_TRUE(one.isPositive());
375
376 Int neg_one(&scope, runtime_->newInt(-1));
377 EXPECT_FALSE(neg_one.isPositive());
378
379 Int max_small_int(&scope, runtime_->newInt(RawSmallInt::kMaxValue));
380 EXPECT_TRUE(max_small_int.isPositive());
381
382 Int min_small_int(&scope, runtime_->newInt(RawSmallInt::kMinValue));
383 EXPECT_FALSE(min_small_int.isPositive());
384
385 Int max_word(&scope, runtime_->newInt(kMaxWord));
386 EXPECT_TRUE(max_word.isPositive());
387
388 Int min_word(&scope, runtime_->newInt(kMinWord));
389 EXPECT_FALSE(min_word.isPositive());
390}
391
392TEST_F(IntTest, IsNegative) {
393 HandleScope scope(thread_);
394
395 Int zero(&scope, runtime_->newInt(0));
396 EXPECT_FALSE(zero.isNegative());
397
398 Int one(&scope, runtime_->newInt(1));
399 EXPECT_FALSE(one.isNegative());
400
401 Int neg_one(&scope, runtime_->newInt(-1));
402 EXPECT_TRUE(neg_one.isNegative());
403
404 Int max_small_int(&scope, runtime_->newInt(RawSmallInt::kMaxValue));
405 EXPECT_FALSE(max_small_int.isNegative());
406
407 Int min_small_int(&scope, runtime_->newInt(RawSmallInt::kMinValue));
408 EXPECT_TRUE(min_small_int.isNegative());
409
410 Int max_word(&scope, runtime_->newInt(kMaxWord));
411 EXPECT_FALSE(max_word.isNegative());
412
413 Int min_word(&scope, runtime_->newInt(kMinWord));
414 EXPECT_TRUE(min_word.isNegative());
415}
416
417TEST_F(IntTest, IsZero) {
418 HandleScope scope(thread_);
419
420 Int zero(&scope, runtime_->newInt(0));
421 EXPECT_TRUE(zero.isZero());
422
423 Int one(&scope, runtime_->newInt(1));
424 EXPECT_FALSE(one.isZero());
425
426 Int neg_one(&scope, runtime_->newInt(-1));
427 EXPECT_FALSE(neg_one.isZero());
428
429 Int max_small_int(&scope, runtime_->newInt(RawSmallInt::kMaxValue));
430 EXPECT_FALSE(max_small_int.isZero());
431
432 Int min_small_int(&scope, runtime_->newInt(RawSmallInt::kMinValue));
433 EXPECT_FALSE(min_small_int.isZero());
434
435 Int max_word(&scope, runtime_->newInt(kMaxWord));
436 EXPECT_FALSE(max_word.isZero());
437
438 Int min_word(&scope, runtime_->newInt(kMinWord));
439 EXPECT_FALSE(min_word.isZero());
440}
441
442TEST_F(IntTest, Compare) {
443 HandleScope scope(thread_);
444
445 Int zero(&scope, runtime_->newInt(0));
446 Int one(&scope, runtime_->newInt(1));
447 Int neg_one(&scope, runtime_->newInt(-1));
448
449 EXPECT_EQ(zero.compare(*zero), 0);
450 EXPECT_GE(one.compare(*neg_one), 1);
451 EXPECT_LE(neg_one.compare(*one), -1);
452
453 Int min_small_int(&scope, runtime_->newInt(RawSmallInt::kMinValue));
454 Int max_small_int(&scope, runtime_->newInt(RawSmallInt::kMaxValue));
455
456 EXPECT_GE(max_small_int.compare(*min_small_int), 1);
457 EXPECT_LE(min_small_int.compare(*max_small_int), -1);
458 EXPECT_EQ(min_small_int.compare(*min_small_int), 0);
459 EXPECT_EQ(max_small_int.compare(*max_small_int), 0);
460
461 Int min_word(&scope, runtime_->newInt(kMinWord));
462 Int max_word(&scope, runtime_->newInt(kMaxWord));
463
464 EXPECT_GE(max_word.compare(*min_word), 1);
465 EXPECT_LE(min_word.compare(*max_word), -1);
466 EXPECT_EQ(min_word.compare(*min_word), 0);
467 EXPECT_EQ(max_word.compare(*max_word), 0);
468
469 EXPECT_GE(max_word.compare(*max_small_int), 1);
470 EXPECT_LE(min_word.compare(*min_small_int), -1);
471}
472
473TEST_F(IntTest, LargeIntCompare) {
474 HandleScope scope(thread_);
475 const uword digits_great[] = {1, 1};
476 Int great(&scope, runtime_->newLargeIntWithDigits(digits_great));
477 const uword digits_small[] = {0, 0, kMaxUword};
478 Int small(&scope, runtime_->newLargeIntWithDigits(digits_small));
479 EXPECT_EQ(great.compare(*small), 1);
480 EXPECT_EQ(small.compare(*great), -1);
481
482 const uword digits_great2[] = {1, 1, 1};
483 const uword digits_small2[] = {1, 1};
484 great = runtime_->newLargeIntWithDigits(digits_great2);
485 small = runtime_->newLargeIntWithDigits(digits_small2);
486 EXPECT_EQ(great.compare(*small), 1);
487 EXPECT_EQ(small.compare(*great), -1);
488
489 const uword digits_great3[] = {kMaxUword - 1, 1};
490 const uword digits_small3[] = {2, 1};
491 great = runtime_->newLargeIntWithDigits(digits_great3);
492 small = runtime_->newLargeIntWithDigits(digits_small3);
493 EXPECT_EQ(great.compare(*small), 1);
494 EXPECT_EQ(small.compare(*great), -1);
495
496 const uword digits_great4[] = {kMaxUword - 1, kMaxUword - 1};
497 const uword digits_small4[] = {2, kMaxUword - 1};
498 great = runtime_->newLargeIntWithDigits(digits_great4);
499 small = runtime_->newLargeIntWithDigits(digits_small4);
500 EXPECT_EQ(great.compare(*small), 1);
501 EXPECT_EQ(small.compare(*great), -1);
502}
503
504#define EXPECT_VALID(expr, expected_value) \
505 { \
506 auto const result = (expr); \
507 EXPECT_EQ(result.error, CastError::None); \
508 EXPECT_EQ(result.value, expected_value); \
509 }
510
511TEST_F(IntTest, AsIntWithZeroReturnsZero) {
512 HandleScope scope(thread_);
513 Int zero(&scope, runtime_->newInt(0));
514 EXPECT_VALID(zero.asInt<int>(), 0);
515 EXPECT_VALID(zero.asInt<unsigned>(), 0U);
516 EXPECT_VALID(zero.asInt<unsigned long>(), 0UL);
517 EXPECT_VALID(zero.asInt<unsigned long long>(), 0ULL);
518}
519
520TEST_F(IntTest, AsIntReturnsInt) {
521 HandleScope scope(thread_);
522 Int num(&scope, runtime_->newInt(1234));
523 EXPECT_VALID(num.asInt<int>(), 1234);
524 EXPECT_VALID(num.asInt<long>(), 1234);
525 EXPECT_VALID(num.asInt<unsigned>(), 1234U);
526 EXPECT_VALID(num.asInt<unsigned long>(), 1234UL);
527}
528
529TEST_F(IntTest, AsIntReturnsOverflow) {
530 HandleScope scope(thread_);
531 Int num(&scope, runtime_->newInt(1234));
532 EXPECT_EQ(num.asInt<byte>().error, CastError::Overflow);
533 EXPECT_EQ(num.asInt<int8_t>().error, CastError::Overflow);
534 Int word_max(&scope, runtime_->newInt(kMaxWord));
535 EXPECT_EQ(word_max.asInt<int32_t>().error, CastError::Overflow);
536 Int word_min(&scope, runtime_->newInt(kMinWord));
537 EXPECT_EQ(word_min.asInt<int32_t>().error, CastError::Overflow);
538}
539
540TEST_F(IntTest, AsIntWithNegativeIntReturnsInt) {
541 HandleScope scope(thread_);
542 Int neg_num(&scope, runtime_->newInt(-4567));
543 EXPECT_VALID(neg_num.asInt<int16_t>(), -4567);
544 Int neg_one(&scope, runtime_->newInt(-1));
545 EXPECT_VALID(neg_one.asInt<int>(), -1);
546}
547
548TEST_F(IntTest, AsIntReturnsUnderflow) {
549 HandleScope scope(thread_);
550 Int neg_num(&scope, runtime_->newInt(-4567));
551 EXPECT_EQ(neg_num.asInt<unsigned>().error, CastError::Underflow);
552 EXPECT_EQ(neg_num.asInt<int8_t>().error, CastError::Underflow);
553 Int neg_one(&scope, runtime_->newInt(-1));
554 EXPECT_EQ(neg_one.asInt<unsigned>().error, CastError::Underflow);
555 Int word_min(&scope, runtime_->newInt(kMinWord));
556 EXPECT_EQ(word_min.asInt<uword>().error, CastError::Underflow);
557}
558
559TEST_F(IntTest, AsIntWithMaxInt32ReturnsInt) {
560 HandleScope scope(thread_);
561 Int int32_max(&scope, runtime_->newInt(kMaxInt32));
562 EXPECT_VALID(int32_max.asInt<int32_t>(), kMaxInt32);
563 EXPECT_EQ(int32_max.asInt<int16_t>().error, CastError::Overflow);
564}
565
566TEST_F(IntTest, AsIntWithMaxUwordReturnsInt) {
567 HandleScope scope(thread_);
568 Int uword_max(&scope, runtime_->newIntFromUnsigned(kMaxUword));
569 EXPECT_VALID(uword_max.asInt<uword>(), kMaxUword);
570 EXPECT_EQ(uword_max.asInt<word>().error, CastError::Overflow);
571}
572
573TEST_F(IntTest, AsIntWithMaxWordReturnsInt) {
574 HandleScope scope(thread_);
575 Int word_max(&scope, runtime_->newInt(kMaxWord));
576 EXPECT_VALID(word_max.asInt<word>(), kMaxWord);
577 EXPECT_VALID(word_max.asInt<uword>(), uword{kMaxWord});
578}
579
580TEST_F(IntTest, AsIntWithMinWordReturnsInt) {
581 HandleScope scope(thread_);
582 Int word_min(&scope, runtime_->newInt(kMinWord));
583 EXPECT_VALID(word_min.asInt<word>(), kMinWord);
584}
585
586TEST_F(IntTest, AsIntWithNegativeLargeIntReturnsUnderflow) {
587 HandleScope scope(thread_);
588 uword digits[] = {0, kMaxUword};
589 Int negative(&scope, runtime_->newLargeIntWithDigits(digits));
590 EXPECT_EQ(negative.asInt<word>().error, CastError::Underflow);
591 EXPECT_EQ(negative.asInt<uword>().error, CastError::Underflow);
592}
593
594TEST_F(IntTest, AsIntWithTrueReturnsOne) {
595 HandleScope scope(thread_);
596 Int value(&scope, Bool::trueObj());
597 EXPECT_VALID(value.asInt<word>(), 1);
598 EXPECT_VALID(value.asInt<uint8_t>(), 1);
599}
600
601TEST_F(IntTest, AsIntWithFalseReturnsZero) {
602 HandleScope scope(thread_);
603 Int value(&scope, Bool::falseObj());
604 EXPECT_VALID(value.asInt<uword>(), uword{0});
605 EXPECT_VALID(value.asInt<int32_t>(), 0);
606}
607
608#undef EXPECT_VALID
609
610TEST_F(IntTest, SmallIntFromWordTruncatedWithSmallNegativeNumberReturnsSelf) {
611 EXPECT_EQ(SmallInt::fromWord(-1), SmallInt::fromWordTruncated(-1));
612}
613
614TEST_F(MmapTest, AccessSettersSetValues) {
615 HandleScope scope(thread_);
616 Object obj(&scope, runtime_->newMmap());
617 ASSERT_TRUE(obj.isMmap());
618 Mmap mmap_obj(&scope, *obj);
619 mmap_obj.setReadable();
620 mmap_obj.setWritable();
621 mmap_obj.setCopyOnWrite();
622 EXPECT_EQ(mmap_obj.isReadable(), true);
623 EXPECT_EQ(mmap_obj.isWritable(), true);
624 EXPECT_EQ(mmap_obj.isCopyOnWrite(), true);
625}
626
627TEST_F(ModulesTest, TestCreate) {
628 HandleScope scope(thread_);
629 Object name(&scope, runtime_->newStrFromCStr("mymodule"));
630 Module module(&scope, runtime_->newModule(name));
631 EXPECT_EQ(module.name(), *name);
632}
633
634TEST_F(MutableBytesTest, BecomeStrTurnsObjectIntoSmallStr) {
635 HandleScope scope(thread_);
636 Object test_0(&scope, runtime_->emptyMutableBytes());
637 ASSERT_TRUE(test_0.isMutableBytes());
638 Object as_str_0(&scope, MutableBytes::cast(*test_0).becomeStr());
639 EXPECT_TRUE(test_0.isMutableBytes());
640 EXPECT_TRUE(as_str_0.isSmallStr());
641 EXPECT_TRUE(isStrEqualsCStr(*as_str_0, ""));
642
643 Str str(&scope, runtime_->newStrFromCStr("abcdefghi"));
644
645 Object test_1(&scope, runtime_->newMutableBytesUninitialized(1));
646 ASSERT_TRUE(test_1.isMutableBytes());
647 MutableBytes::cast(*test_1).replaceFromWithStr(0, *str, 1);
648 Object as_str_1(&scope, MutableBytes::cast(*test_1).becomeStr());
649 EXPECT_TRUE(test_1.isMutableBytes());
650 EXPECT_TRUE(as_str_1.isSmallStr());
651 EXPECT_TRUE(isStrEqualsCStr(*as_str_1, "a"));
652
653 Object test_m(&scope,
654 runtime_->newMutableBytesUninitialized(SmallStr::kMaxLength));
655 ASSERT_TRUE(test_m.isMutableBytes());
656 MutableBytes::cast(*test_m).replaceFromWithStr(0, *str, SmallStr::kMaxLength);
657 Object as_str_m(&scope, MutableBytes::cast(*test_m).becomeStr());
658 EXPECT_TRUE(test_m.isMutableBytes());
659 EXPECT_TRUE(as_str_m.isSmallStr());
660 EXPECT_TRUE(isStrEqualsCStr(*as_str_m, "abcdefg"));
661}
662
663TEST_F(MutableBytesTest, BecomeStrTurnsObjectIntoLargeStr) {
664 HandleScope scope(thread_);
665 Str str(&scope, runtime_->newStrFromCStr("hello world!"));
666
667 Object test(&scope, runtime_->newMutableBytesUninitialized(str.length()));
668 ASSERT_TRUE(test.isMutableBytes());
669 MutableBytes::cast(*test).replaceFromWithStr(0, *str, str.length());
670 MutableBytes::cast(*test).becomeStr();
671 EXPECT_TRUE(test.isLargeStr());
672 EXPECT_TRUE(isStrEqualsCStr(*test, "hello world!"));
673}
674
675TEST_F(SliceTest, AdjustIndices) {
676 // Test: 0:10:1 on len: 10
677 word length = 10;
678 word start = 0;
679 word stop = 10;
680 word step = 1;
681 word new_length = Slice::adjustIndices(length, &start, &stop, step);
682 ASSERT_EQ(new_length, 10);
683 ASSERT_EQ(start, 0);
684 ASSERT_EQ(stop, 10);
685
686 // Test: 2:10:1 on len: 10
687 start = 2;
688 new_length = Slice::adjustIndices(length, &start, &stop, step);
689 ASSERT_EQ(new_length, 8);
690 ASSERT_EQ(start, 2);
691 ASSERT_EQ(stop, 10);
692
693 // Test: -4:10:1 on len: 10
694 start = -4;
695 new_length = Slice::adjustIndices(length, &start, &stop, step);
696 ASSERT_EQ(new_length, 4);
697 ASSERT_EQ(start, 6);
698 ASSERT_EQ(stop, 10);
699
700 // Test: 0:2:1 on len: 10
701 start = 0;
702 stop = 2;
703 new_length = Slice::adjustIndices(length, &start, &stop, step);
704 ASSERT_EQ(new_length, 2);
705 ASSERT_EQ(start, 0);
706 ASSERT_EQ(stop, 2);
707
708 // Test: 0:-2:1 on len: 10
709 start = 0;
710 stop = -2;
711 new_length = Slice::adjustIndices(length, &start, &stop, step);
712 ASSERT_EQ(new_length, 8);
713 ASSERT_EQ(start, 0);
714 ASSERT_EQ(stop, 8);
715
716 // Test: 0:10:2 on len: 10
717 start = 0;
718 stop = 10;
719 step = 2;
720 new_length = Slice::adjustIndices(length, &start, &stop, step);
721 ASSERT_EQ(new_length, 5);
722 ASSERT_EQ(start, 0);
723 ASSERT_EQ(stop, 10);
724
725 // Test: 0:10:-2 on len: 10
726 start = 0;
727 stop = 10;
728 step = -2;
729 new_length = Slice::adjustIndices(length, &start, &stop, step);
730 ASSERT_EQ(new_length, 0);
731 ASSERT_EQ(start, 0);
732 ASSERT_EQ(stop, 9);
733}
734
735TEST_F(SliceTest, AdjustIndicesOutOfBounds) {
736 // Test: 10:5:1 on len: 5
737 word length = 5;
738 word start = 10;
739 word stop = 5;
740 word step = 1;
741 word new_length = Slice::adjustIndices(length, &start, &stop, step);
742 ASSERT_EQ(new_length, 0);
743 ASSERT_EQ(start, 5);
744 ASSERT_EQ(stop, 5);
745
746 // Test: -10:5:1 on len: 5
747 start = -10;
748 new_length = Slice::adjustIndices(length, &start, &stop, step);
749 ASSERT_EQ(new_length, 5);
750 ASSERT_EQ(start, 0);
751 ASSERT_EQ(stop, 5);
752
753 // Test: 0:10:1 on len: 5
754 start = 0;
755 stop = 10;
756 new_length = Slice::adjustIndices(length, &start, &stop, step);
757 ASSERT_EQ(new_length, 5);
758 ASSERT_EQ(start, 0);
759 ASSERT_EQ(stop, 5);
760
761 // Test: 0:-10:1 on len: 5
762 stop = -10;
763 new_length = Slice::adjustIndices(length, &start, &stop, step);
764 ASSERT_EQ(new_length, 0);
765 ASSERT_EQ(start, 0);
766 ASSERT_EQ(stop, 0);
767
768 // Test: 0:5:10 on len: 5
769 stop = 5;
770 step = 10;
771 new_length = Slice::adjustIndices(length, &start, &stop, step);
772 ASSERT_EQ(new_length, 1);
773 ASSERT_EQ(start, 0);
774 ASSERT_EQ(stop, 5);
775
776 // Test: 0:5:-10 on len: 5
777 step = -10;
778 new_length = Slice::adjustIndices(length, &start, &stop, step);
779 ASSERT_EQ(new_length, 0);
780 ASSERT_EQ(start, 0);
781 ASSERT_EQ(stop, 4);
782}
783
784TEST_F(SliceTest, LengthWithNegativeStepAndStopLessThanStartReturnsLength) {
785 EXPECT_EQ(Slice::length(5, 2, -1), 3);
786}
787
788TEST_F(SliceTest, LengthWithNegativeStepAndStartLessThanStopReturnsZero) {
789 EXPECT_EQ(Slice::length(2, 5, -1), 0);
790}
791
792TEST_F(SliceTest, LengthWithNegativeStepAndStartEqualsStopReturnsZero) {
793 EXPECT_EQ(Slice::length(2, 2, -1), 0);
794}
795
796TEST_F(SliceTest, LengthWithPositiveStepAndStartLessThanStopReturnsLength) {
797 EXPECT_EQ(Slice::length(2, 5, 1), 3);
798}
799
800TEST_F(SliceTest, LengthWithPositiveStepAndStopLessThanStartReturnsZero) {
801 EXPECT_EQ(Slice::length(5, 2, 1), 0);
802}
803
804TEST_F(SliceTest, LengthWithPositiveStepAndStartEqualsStopReturnsZero) {
805 EXPECT_EQ(Slice::length(2, 2, 1), 0);
806}
807
808TEST_F(StrArrayTest, OffsetByCodePoints) {
809 HandleScope scope(thread_);
810
811 StrArray empty(&scope, runtime_->newStrArray());
812 EXPECT_EQ(empty.numItems(), 0);
813 EXPECT_EQ(empty.offsetByCodePoints(0, 1), 0);
814 EXPECT_EQ(empty.offsetByCodePoints(2, 0), 0);
815 EXPECT_EQ(empty.offsetByCodePoints(2, 1), 0);
816
817 StrArray ascii(&scope, runtime_->newStrArray());
818 Str ascii_str(&scope, runtime_->newStrFromCStr("abcd"));
819 runtime_->strArrayAddStr(thread_, ascii, ascii_str);
820 EXPECT_EQ(ascii.numItems(), 4);
821
822 // for ASCII, each code point is one byte wide
823 EXPECT_EQ(ascii.offsetByCodePoints(0, 0), 0);
824 EXPECT_EQ(ascii.offsetByCodePoints(0, 3), 3);
825 EXPECT_EQ(ascii.offsetByCodePoints(1, 0), 1);
826 EXPECT_EQ(ascii.offsetByCodePoints(2, 0), 2);
827 EXPECT_EQ(ascii.offsetByCodePoints(2, 1), 3);
828 EXPECT_EQ(ascii.offsetByCodePoints(3, 0), 3);
829
830 // return the length once we reach the end of the string
831 EXPECT_EQ(ascii.offsetByCodePoints(0, 4), 4);
832 EXPECT_EQ(ascii.offsetByCodePoints(0, 5), 4);
833 EXPECT_EQ(ascii.offsetByCodePoints(1, 3), 4);
834 EXPECT_EQ(ascii.offsetByCodePoints(1, 4), 4);
835 EXPECT_EQ(ascii.offsetByCodePoints(2, 2), 4);
836 EXPECT_EQ(ascii.offsetByCodePoints(2, 3), 4);
837 EXPECT_EQ(ascii.offsetByCodePoints(3, 1), 4);
838 EXPECT_EQ(ascii.offsetByCodePoints(3, 2), 4);
839 EXPECT_EQ(ascii.offsetByCodePoints(4, 0), 4);
840 EXPECT_EQ(ascii.offsetByCodePoints(6, 0), 4);
841
842 StrArray unicode(&scope, runtime_->newStrArray());
843 Str unicode_str(
844 &scope, runtime_->newStrFromCStr("\xd7\x90pq\xd7\x91\xd7\x92-\xd7\x93"));
845 runtime_->strArrayAddStr(thread_, unicode, unicode_str);
846 EXPECT_EQ(unicode.numItems(), 11);
847
848 // for Unicode, code points may be more than one byte wide
849 EXPECT_EQ(unicode.offsetByCodePoints(0, 0), 0);
850 EXPECT_EQ(unicode.offsetByCodePoints(0, 1), 2);
851 EXPECT_EQ(unicode.offsetByCodePoints(0, 2), 3);
852 EXPECT_EQ(unicode.offsetByCodePoints(0, 3), 4);
853 EXPECT_EQ(unicode.offsetByCodePoints(0, 4), 6);
854 EXPECT_EQ(unicode.offsetByCodePoints(0, 5), 8);
855 EXPECT_EQ(unicode.offsetByCodePoints(0, 6), 9);
856 EXPECT_EQ(unicode.offsetByCodePoints(2, 0), 2);
857 EXPECT_EQ(unicode.offsetByCodePoints(2, 1), 3);
858 EXPECT_EQ(unicode.offsetByCodePoints(2, 2), 4);
859 EXPECT_EQ(unicode.offsetByCodePoints(2, 3), 6);
860 EXPECT_EQ(unicode.offsetByCodePoints(2, 4), 8);
861 EXPECT_EQ(unicode.offsetByCodePoints(2, 5), 9);
862 EXPECT_EQ(unicode.offsetByCodePoints(2, 6), 11);
863 EXPECT_EQ(unicode.offsetByCodePoints(4, 0), 4);
864 EXPECT_EQ(unicode.offsetByCodePoints(4, 1), 6);
865 EXPECT_EQ(unicode.offsetByCodePoints(6, 0), 6);
866
867 // return the length once we reach the end of the string
868 EXPECT_EQ(unicode.offsetByCodePoints(0, 7), 11);
869 EXPECT_EQ(unicode.offsetByCodePoints(0, 9), 11);
870 EXPECT_EQ(unicode.offsetByCodePoints(2, 7), 11);
871 EXPECT_EQ(unicode.offsetByCodePoints(3, 6), 11);
872 EXPECT_EQ(unicode.offsetByCodePoints(4, 5), 11);
873 EXPECT_EQ(unicode.offsetByCodePoints(8, 3), 11);
874 EXPECT_EQ(unicode.offsetByCodePoints(12, 0), 11);
875}
876
877TEST_F(StrArrayTest, RotateCodePointWithSameFirstAndLastIsNoop) {
878 HandleScope scope(thread_);
879 StrArray array(&scope, runtime_->newStrArray());
880 runtime_->strArrayAddASCII(thread_, array, 'H');
881 runtime_->strArrayAddASCII(thread_, array, 'i');
882 runtime_->strArrayAddASCII(thread_, array, '!');
883 EXPECT_TRUE(isStrEqualsCStr(runtime_->strFromStrArray(array), "Hi!"));
884
885 array.rotateCodePoint(1, 1);
886 EXPECT_TRUE(isStrEqualsCStr(runtime_->strFromStrArray(array), "Hi!"));
887}
888
889TEST_F(StrArrayTest, RotateCodePointWithFirstBeforeLastRotatesCodePoint) {
890 HandleScope scope(thread_);
891 StrArray array(&scope, runtime_->newStrArray());
892 runtime_->strArrayAddASCII(thread_, array, 'a');
893 runtime_->strArrayAddASCII(thread_, array, 'b');
894 runtime_->strArrayAddASCII(thread_, array, 'c');
895 EXPECT_TRUE(isStrEqualsCStr(runtime_->strFromStrArray(array), "abc"));
896
897 array.rotateCodePoint(0, 2);
898 EXPECT_TRUE(isStrEqualsCStr(runtime_->strFromStrArray(array), "cab"));
899}
900
901TEST_F(StrArrayTest, RotateCodePointWithNonASCIIRotatesEntireCodePoint) {
902 HandleScope scope(thread_);
903 StrArray array(&scope, runtime_->newStrArray());
904 Str str(&scope, runtime_->newStrFromCStr("Chopin \u00e9tude"));
905 runtime_->strArrayAddStr(thread_, array, str);
906
907 array.rotateCodePoint(1, 7);
908 EXPECT_TRUE(
909 isStrEqualsCStr(runtime_->strFromStrArray(array), "C\u00e9hopin tude"));
910}
911
912TEST_F(StrArrayTest, RotateCodePointWithNonASCIIUsesCharIndex) {
913 HandleScope scope(thread_);
914 StrArray array(&scope, runtime_->newStrArray());
915 Str str(&scope, runtime_->newStrFromCStr("Chopin \u00e9tude"));
916 runtime_->strArrayAddStr(thread_, array, str);
917
918 array.rotateCodePoint(1, 10);
919 EXPECT_TRUE(
920 isStrEqualsCStr(runtime_->strFromStrArray(array), "Cuhopin \u00e9tde"));
921}
922
923TEST_F(LargeStrTest, CopyTo) {
924 RawObject obj = runtime_->newStrFromCStr("hello world!");
925 ASSERT_TRUE(obj.isLargeStr());
926 RawStr str = Str::cast(obj);
927
928 byte array[5];
929 memset(array, 'a', ARRAYSIZE(array));
930 str.copyTo(array, 0);
931 EXPECT_EQ(array[0], 'a');
932 EXPECT_EQ(array[1], 'a');
933 EXPECT_EQ(array[2], 'a');
934 EXPECT_EQ(array[3], 'a');
935 EXPECT_EQ(array[4], 'a');
936
937 memset(array, 'b', ARRAYSIZE(array));
938 str.copyTo(array, 1);
939 EXPECT_EQ(array[0], 'h');
940 EXPECT_EQ(array[1], 'b');
941 EXPECT_EQ(array[2], 'b');
942 EXPECT_EQ(array[3], 'b');
943 EXPECT_EQ(array[4], 'b');
944
945 memset(array, 'c', ARRAYSIZE(array));
946 str.copyTo(array, 5);
947 EXPECT_EQ(array[0], 'h');
948 EXPECT_EQ(array[1], 'e');
949 EXPECT_EQ(array[2], 'l');
950 EXPECT_EQ(array[3], 'l');
951 EXPECT_EQ(array[4], 'o');
952}
953
954TEST_F(StringTest, CompareSmallStrCStrASCII) {
955 HandleScope scope(thread_);
956
957 Str small_ascii(&scope, runtime_->newStrFromCStr("sm"));
958 ASSERT_TRUE(small_ascii.isSmallStr());
959
960 // Equal
961 EXPECT_EQ(small_ascii.compareCStr("sm"), 0);
962
963 // Less
964 EXPECT_EQ(small_ascii.compareCStr("sma"), -1);
965 EXPECT_EQ(small_ascii.compareCStr("sn"), -1);
966
967 // Greater
968 EXPECT_EQ(small_ascii.compareCStr("s"), 1);
969 EXPECT_EQ(small_ascii.compareCStr("sl"), 1);
970}
971
972TEST_F(StringTest, CompareSmallStrWithNulCStrASCII) {
973 HandleScope scope(thread_);
974
975 const byte data[] = {'s', '\0', 'm'};
976 Str small_ascii(&scope, runtime_->newStrWithAll(data));
977 ASSERT_TRUE(small_ascii.isSmallStr());
978
979 // Less
980 EXPECT_EQ(small_ascii.compareCStr("t"), -1);
981
982 // Greater
983 EXPECT_EQ(small_ascii.compareCStr("s"), 1);
984 EXPECT_EQ(small_ascii.compareCStr("a\0m"), 1);
985}
986
987TEST_F(StringTest, CompareLargeStrWithNulCStrASCII) {
988 HandleScope scope(thread_);
989
990 const byte data[] = {'l', 'a', 'r', 'g', 'e', '\0', 's', 't'};
991 Str large_ascii(&scope, runtime_->newStrWithAll(data));
992 ASSERT_TRUE(large_ascii.isLargeStr());
993
994 // Less
995 EXPECT_EQ(large_ascii.compareCStr("largz"), -1);
996
997 // Greater
998 EXPECT_EQ(large_ascii.compareCStr("large"), 1);
999 EXPECT_EQ(large_ascii.compareCStr("larga\0st"), 1);
1000}
1001
1002TEST_F(StringTest, CompareLargeStrCStrASCII) {
1003 HandleScope scope(thread_);
1004
1005 Str large_ascii(&scope, runtime_->newStrFromCStr("large string"));
1006 ASSERT_TRUE(large_ascii.isLargeStr());
1007
1008 // Equal
1009 EXPECT_EQ(large_ascii.compareCStr("large string"), 0);
1010
1011 // Less
1012 EXPECT_EQ(large_ascii.compareCStr("large strings"), -1);
1013 EXPECT_EQ(large_ascii.compareCStr("large tbigger"), -1);
1014
1015 // Greater
1016 EXPECT_EQ(large_ascii.compareCStr("large strin"), 1);
1017 EXPECT_EQ(large_ascii.compareCStr("large smaller"), 1);
1018}
1019
1020TEST_F(StringTest, CompareSmallStrCStrUTF8) {
1021 HandleScope scope(thread_);
1022
1023 Str small_utf8(&scope, runtime_->newStrFromCStr("\xC3\x87"));
1024 ASSERT_TRUE(small_utf8.isSmallStr());
1025
1026 // Equal
1027 EXPECT_EQ(small_utf8.compareCStr("\xC3\x87"), 0);
1028
1029 // Less
1030 EXPECT_EQ(small_utf8.compareCStr("\xC3\x87s"), -1);
1031 EXPECT_EQ(small_utf8.compareCStr("\xC3\x88"), -1);
1032 EXPECT_EQ(small_utf8.compareCStr("\xC3\xA7"), -1);
1033
1034 // Greater
1035 EXPECT_EQ(small_utf8.compareCStr(""), 1);
1036 EXPECT_EQ(small_utf8.compareCStr("\xC3\x86"), 1);
1037 EXPECT_EQ(small_utf8.compareCStr("\xC3\x67"), 1);
1038}
1039
1040TEST_F(StringTest, CompareLargeStrCStrUTF8) {
1041 HandleScope scope(thread_);
1042
1043 Str large_utf8(&scope, runtime_->newStrFromCStr("\xC3\x87 large"));
1044 ASSERT_TRUE(large_utf8.isLargeStr());
1045
1046 // Equal
1047 EXPECT_EQ(large_utf8.compareCStr("\xC3\x87 large"), 0);
1048
1049 // Less
1050 EXPECT_EQ(large_utf8.compareCStr("\xC3\x87 larges"), -1);
1051 EXPECT_EQ(large_utf8.compareCStr("\xC3\x88 large"), -1);
1052 EXPECT_EQ(large_utf8.compareCStr("\xC3\xA7 large"), -1);
1053
1054 // Greater
1055 EXPECT_EQ(large_utf8.compareCStr("\xC3\x87"), 1);
1056 EXPECT_EQ(large_utf8.compareCStr("\xC3\x86 large"), 1);
1057 EXPECT_EQ(large_utf8.compareCStr("g large"), 1);
1058}
1059
1060TEST_F(StringTest, CompareSmallStrCStrLatin1) {
1061 HandleScope scope(thread_);
1062
1063 Str small_latin1(&scope, runtime_->newStrFromCStr("\xDC"));
1064 ASSERT_TRUE(small_latin1.isSmallStr());
1065
1066 // Equal
1067 EXPECT_EQ(small_latin1.compareCStr("\xDC"), 0);
1068
1069 // Less
1070 EXPECT_EQ(small_latin1.compareCStr("\xDCs"), -1);
1071 EXPECT_EQ(small_latin1.compareCStr("\xDD"), -1);
1072 EXPECT_EQ(small_latin1.compareCStr("\xEC"), -1);
1073
1074 // Greater
1075 EXPECT_EQ(small_latin1.compareCStr(""), 1);
1076 EXPECT_EQ(small_latin1.compareCStr("\xDB"), 1);
1077 EXPECT_EQ(small_latin1.compareCStr("\xAC"), 1);
1078}
1079
1080TEST_F(StringTest, CompareLargeStrCStrLatin1) {
1081 HandleScope scope(thread_);
1082
1083 Str large_latin1(&scope, runtime_->newStrFromCStr("\xDClarge str"));
1084 ASSERT_TRUE(large_latin1.isLargeStr());
1085
1086 // Equal
1087 EXPECT_EQ(large_latin1.compareCStr("\xDClarge str"), 0);
1088
1089 // Less
1090 EXPECT_EQ(large_latin1.compareCStr("\xDClarge strs"), -1);
1091 EXPECT_EQ(large_latin1.compareCStr("\xDDlarge str"), -1);
1092 EXPECT_EQ(large_latin1.compareCStr("\xEClarge str"), -1);
1093
1094 // Greater
1095 EXPECT_EQ(large_latin1.compareCStr("\xDC"), 1);
1096 EXPECT_EQ(large_latin1.compareCStr("\xDBlarge str"), 1);
1097 EXPECT_EQ(large_latin1.compareCStr("\xBClarge str"), 1);
1098}
1099
1100TEST_F(StringTest, CopyToStartAtWithLargeStrCopiesBytes) {
1101 HandleScope scope(thread_);
1102 Str str(&scope, runtime_->newStrFromCStr("Hello world!"));
1103
1104 byte actual0[5];
1105 LargeStr::cast(*str).copyToStartAt(actual0, 5, 3);
1106 EXPECT_EQ(std::memcmp(actual0, "lo", 2), 0);
1107
1108 byte actual1[3];
1109 LargeStr::cast(*str).copyToStartAt(actual1, 3, 4);
1110 EXPECT_EQ(std::memcmp(actual1, "o w", 3), 0);
1111
1112 // zero-sized copies should do nothing.
1113 str.copyToStartAt(nullptr, 0, 0);
1114 LargeStr::cast(*str).copyToStartAt(nullptr, 0, 12);
1115}
1116
1117TEST_F(StringTest, CopyToStartAtWithSmallStrCopiesBytes) {
1118 HandleScope scope(thread_);
1119 Str str(&scope, SmallStr::fromCStr("bar"));
1120
1121 byte actual0[3];
1122 str.copyToStartAt(actual0, 3, 0);
1123 EXPECT_EQ(std::memcmp(actual0, "bar", 3), 0);
1124
1125 byte actual1[2];
1126 str.copyToStartAt(actual1, 2, 1);
1127 EXPECT_EQ(std::memcmp(actual1, "ar", 2), 0);
1128
1129 // zero-sized copies should do nothing.
1130 str.copyToStartAt(nullptr, 0, 0);
1131 str.copyToStartAt(nullptr, 0, 3);
1132}
1133
1134TEST_F(SmallStrTest, CodePointLengthWithAsciiReturnsLength) {
1135 HandleScope scope(thread_);
1136 SmallStr len0(&scope, SmallStr::fromCStr(""));
1137 EXPECT_EQ(len0.length(), 0);
1138 EXPECT_EQ(len0.codePointLength(), 0);
1139
1140 SmallStr len1(&scope, SmallStr::fromCStr("1"));
1141 EXPECT_EQ(len1.length(), 1);
1142 EXPECT_EQ(len1.codePointLength(), 1);
1143
1144 SmallStr len2(&scope, SmallStr::fromCStr("12"));
1145 EXPECT_EQ(len2.length(), 2);
1146 EXPECT_EQ(len2.codePointLength(), 2);
1147
1148 SmallStr len3(&scope, SmallStr::fromCStr("123"));
1149 EXPECT_EQ(len3.length(), 3);
1150 EXPECT_EQ(len3.codePointLength(), 3);
1151}
1152
1153TEST_F(SmallStrTest, CodePointLengthWithOneCodePoint) {
1154 HandleScope scope(thread_);
1155 SmallStr len1(&scope, SmallStr::fromCStr("\x24"));
1156 EXPECT_EQ(len1.length(), 1);
1157 EXPECT_EQ(len1.codePointLength(), 1);
1158
1159 SmallStr len2(&scope, SmallStr::fromCStr("\xC2\xA2"));
1160 EXPECT_EQ(len2.length(), 2);
1161 EXPECT_EQ(len2.codePointLength(), 1);
1162
1163 SmallStr len3(&scope, SmallStr::fromCStr("\xE0\xA4\xB9"));
1164 EXPECT_EQ(len3.length(), 3);
1165 EXPECT_EQ(len3.codePointLength(), 1);
1166
1167 SmallStr len4(&scope, SmallStr::fromCStr("\xF0\x90\x8D\x88"));
1168 EXPECT_EQ(len4.length(), 4);
1169 EXPECT_EQ(len4.codePointLength(), 1);
1170}
1171
1172TEST_F(SmallStrTest, CodePointLengthWithTwoCodePoints) {
1173 HandleScope scope(thread_);
1174 SmallStr len1(&scope, SmallStr::fromCStr("\x24\x65"));
1175 EXPECT_EQ(len1.length(), 2);
1176 EXPECT_EQ(len1.codePointLength(), 2);
1177
1178 SmallStr len2(&scope, SmallStr::fromCStr("\xC2\xA2\xC2\xA3"));
1179 EXPECT_EQ(len2.length(), 4);
1180 EXPECT_EQ(len2.codePointLength(), 2);
1181
1182 SmallStr len3(&scope, SmallStr::fromCStr("\xE0\xA4\xB9\xC2\xA3"));
1183 EXPECT_EQ(len3.length(), 5);
1184 EXPECT_EQ(len3.codePointLength(), 2);
1185
1186 SmallStr len4(&scope, SmallStr::fromCStr("\xF0\x90\x8D\x88\xC2\xA3"));
1187 EXPECT_EQ(len4.length(), 6);
1188 EXPECT_EQ(len4.codePointLength(), 2);
1189}
1190
1191TEST_F(SmallStrTest, CodePointLengthWithThreeCodePoints) {
1192 HandleScope scope(thread_);
1193 SmallStr len1(&scope, SmallStr::fromCStr("\x24\x65\x66"));
1194 EXPECT_EQ(len1.length(), 3);
1195 EXPECT_EQ(len1.codePointLength(), 3);
1196
1197 SmallStr len2(&scope, SmallStr::fromCStr("\xC2\xA2\xC2\xA3\xC2\xA4"));
1198 EXPECT_EQ(len2.length(), 6);
1199 EXPECT_EQ(len2.codePointLength(), 3);
1200
1201 SmallStr len3(&scope, SmallStr::fromCStr("\xE0\xA4\xB9\xC2\xA3\xC2\xA4"));
1202 EXPECT_EQ(len3.length(), 7);
1203 EXPECT_EQ(len3.codePointLength(), 3);
1204
1205 SmallStr len4(&scope, SmallStr::fromCStr("\xF0\x90\x8D\x88\x65\xC2\xA3"));
1206 EXPECT_EQ(len4.length(), 7);
1207 EXPECT_EQ(len4.codePointLength(), 3);
1208}
1209
1210TEST_F(SmallStrTest, CopyToCopiesBytes) {
1211 HandleScope scope(thread_);
1212 SmallStr str(&scope, SmallStr::fromCStr("AB"));
1213 EXPECT_EQ(str.length(), 2);
1214 EXPECT_EQ(str.byteAt(0), 'A');
1215 EXPECT_EQ(str.byteAt(1), 'B');
1216
1217 byte array[3]{0, 0, 0};
1218 str.copyTo(array, 2);
1219 EXPECT_EQ(array[0], 'A');
1220 EXPECT_EQ(array[1], 'B');
1221 EXPECT_EQ(array[2], 0);
1222}
1223
1224TEST_F(SmallStrTest, FromCodePointOneByte) {
1225 HandleScope scope(thread_);
1226 SmallStr str(&scope, SmallStr::fromCodePoint(0x24));
1227 ASSERT_EQ(str.length(), 1);
1228 EXPECT_EQ(str.byteAt(0), 0x24);
1229}
1230
1231TEST_F(SmallStrTest, FromCodePointTwoByte) {
1232 HandleScope scope(thread_);
1233 SmallStr str(&scope, SmallStr::fromCodePoint(0xA2));
1234 ASSERT_EQ(str.length(), 2);
1235 EXPECT_EQ(str.byteAt(0), 0xC2);
1236 EXPECT_EQ(str.byteAt(1), 0xA2);
1237}
1238
1239TEST_F(SmallStrTest, FromCodePointThreeByte) {
1240 HandleScope scope(thread_);
1241 SmallStr str1(&scope, SmallStr::fromCodePoint(0x0939));
1242 ASSERT_EQ(str1.length(), 3);
1243 EXPECT_EQ(str1.byteAt(0), 0xE0);
1244 EXPECT_EQ(str1.byteAt(1), 0xA4);
1245 EXPECT_EQ(str1.byteAt(2), 0xB9);
1246
1247 SmallStr str2(&scope, SmallStr::fromCodePoint(0x20AC));
1248 ASSERT_EQ(str2.length(), 3);
1249 EXPECT_EQ(str2.byteAt(0), 0xE2);
1250 EXPECT_EQ(str2.byteAt(1), 0x82);
1251 EXPECT_EQ(str2.byteAt(2), 0xAC);
1252}
1253
1254TEST_F(SmallStrTest, FromCodePointFourByte) {
1255 HandleScope scope(thread_);
1256 SmallStr str(&scope, SmallStr::fromCodePoint(0x10348));
1257 ASSERT_EQ(str.length(), 4);
1258 EXPECT_EQ(str.byteAt(0), 0xF0);
1259 EXPECT_EQ(str.byteAt(1), 0x90);
1260 EXPECT_EQ(str.byteAt(2), 0x8D);
1261 EXPECT_EQ(str.byteAt(3), 0x88);
1262}
1263
1264TEST_F(SmallStrTest, IncludesLargeStrReturnsFalse) {
1265 HandleScope scope(thread_);
1266 SmallStr haystack(&scope, SmallStr::fromCStr("abcd"));
1267 LargeStr needle(&scope, runtime_->newStrFromCStr("abcdefgh"));
1268 EXPECT_FALSE(haystack.includes(*needle));
1269}
1270
1271TEST_F(SmallStrTest, IncludesSmallStrChecksSubstr) {
1272 HandleScope scope(thread_);
1273 SmallStr haystack(&scope, SmallStr::fromCStr("abcd"));
1274 SmallStr empty(&scope, Str::empty());
1275 SmallStr needle(&scope, SmallStr::fromCStr("bc"));
1276 SmallStr not_needle(&scope, SmallStr::fromCStr("abcde"));
1277
1278 EXPECT_TRUE(haystack.includes(*empty));
1279 EXPECT_TRUE(haystack.includes(*needle));
1280 EXPECT_TRUE(haystack.includes(*haystack));
1281 EXPECT_FALSE(haystack.includes(*not_needle));
1282}
1283
1284TEST_F(SmallStrTest, IsASCIIReturnsTrueIfAndOnlyIfAllASCII) {
1285 HandleScope scope(thread_);
1286 SmallStr all_ascii(&scope, SmallStr::fromCStr("abc"));
1287 EXPECT_TRUE(all_ascii.isASCII());
1288
1289 SmallStr some_non_ascii(&scope, SmallStr::fromCStr("a\xC2\xA3g"));
1290 EXPECT_FALSE(some_non_ascii.isASCII());
1291}
1292
1293TEST_F(SmallStrTest, OccurrencesOfWithEmptyStringReturnsZero) {
1294 HandleScope scope(thread_);
1295 Str haystack(&scope, SmallStr::fromCStr("hello"));
1296 Str needle(&scope, runtime_->newStrFromCStr(""));
1297 EXPECT_EQ(haystack.occurrencesOf(*needle), 0);
1298}
1299
1300TEST_F(SmallStrTest, OccurrencesOfWithLargeStrReturnsZero) {
1301 HandleScope scope(thread_);
1302 Str haystack(&scope, SmallStr::fromCStr("abab"));
1303 Str needle(&scope, runtime_->newStrFromCStr("ababababab"));
1304 EXPECT_EQ(haystack.occurrencesOf(*needle), 0);
1305}
1306
1307TEST_F(SmallStrTest, OccurrencesOfWithNoOccurenceReturnsZero) {
1308 HandleScope scope(thread_);
1309 Str haystack(&scope, SmallStr::fromCStr("abab"));
1310 Str needle(&scope, SmallStr::fromCStr("cd"));
1311 EXPECT_EQ(haystack.occurrencesOf(*needle), 0);
1312}
1313
1314TEST_F(SmallStrTest, OccurrencesOfWithSmallStrFindsOccurrenceAtSecondChar) {
1315 HandleScope scope(thread_);
1316 Str haystack(&scope, SmallStr::fromCStr("abab"));
1317 Str needle(&scope, SmallStr::fromCStr("ba"));
1318 EXPECT_EQ(haystack.occurrencesOf(*needle), 1);
1319}
1320
1321TEST_F(SmallStrTest, OccurrencesOfWithSmallStrMultipleOccurrencesFindsAll) {
1322 HandleScope scope(thread_);
1323 Str haystack(&scope, SmallStr::fromCStr("hello"));
1324 Str needle(&scope, SmallStr::fromCStr("l"));
1325 EXPECT_EQ(haystack.occurrencesOf(*needle), 2);
1326}
1327
1328TEST_F(StrTest, OffsetByCodePoints) {
1329 HandleScope scope(thread_);
1330
1331 Str empty(&scope, Str::empty());
1332 EXPECT_EQ(empty.length(), 0);
1333 EXPECT_EQ(empty.codePointLength(), 0);
1334 EXPECT_EQ(empty.offsetByCodePoints(0, 1), 0);
1335 EXPECT_EQ(empty.offsetByCodePoints(2, 0), 0);
1336 EXPECT_EQ(empty.offsetByCodePoints(2, 1), 0);
1337
1338 Str ascii(&scope, runtime_->newStrFromCStr("abcd"));
1339 EXPECT_EQ(ascii.length(), 4);
1340 EXPECT_EQ(ascii.codePointLength(), 4);
1341
1342 // for ASCII, each code point is one byte wide
1343 EXPECT_EQ(ascii.offsetByCodePoints(0, 0), 0);
1344 EXPECT_EQ(ascii.offsetByCodePoints(0, 3), 3);
1345 EXPECT_EQ(ascii.offsetByCodePoints(1, 0), 1);
1346 EXPECT_EQ(ascii.offsetByCodePoints(2, 0), 2);
1347 EXPECT_EQ(ascii.offsetByCodePoints(2, 1), 3);
1348 EXPECT_EQ(ascii.offsetByCodePoints(3, 0), 3);
1349
1350 // return the length once we reach the end of the string
1351 EXPECT_EQ(ascii.offsetByCodePoints(0, 4), 4);
1352 EXPECT_EQ(ascii.offsetByCodePoints(0, 5), 4);
1353 EXPECT_EQ(ascii.offsetByCodePoints(1, 3), 4);
1354 EXPECT_EQ(ascii.offsetByCodePoints(1, 4), 4);
1355 EXPECT_EQ(ascii.offsetByCodePoints(2, 2), 4);
1356 EXPECT_EQ(ascii.offsetByCodePoints(2, 3), 4);
1357 EXPECT_EQ(ascii.offsetByCodePoints(3, 1), 4);
1358 EXPECT_EQ(ascii.offsetByCodePoints(3, 2), 4);
1359 EXPECT_EQ(ascii.offsetByCodePoints(4, 0), 4);
1360 EXPECT_EQ(ascii.offsetByCodePoints(6, 0), 4);
1361
1362 Str unicode(&scope,
1363 runtime_->newStrFromCStr("\xd7\x90pq\xd7\x91\xd7\x92-\xd7\x93"));
1364 EXPECT_EQ(unicode.length(), 11);
1365 EXPECT_EQ(unicode.codePointLength(), 7);
1366
1367 // for Unicode, code points may be more than one byte wide
1368 EXPECT_EQ(unicode.offsetByCodePoints(0, 0), 0);
1369 EXPECT_EQ(unicode.offsetByCodePoints(0, 1), 2);
1370 EXPECT_EQ(unicode.offsetByCodePoints(0, 2), 3);
1371 EXPECT_EQ(unicode.offsetByCodePoints(0, 3), 4);
1372 EXPECT_EQ(unicode.offsetByCodePoints(0, 4), 6);
1373 EXPECT_EQ(unicode.offsetByCodePoints(0, 5), 8);
1374 EXPECT_EQ(unicode.offsetByCodePoints(0, 6), 9);
1375 EXPECT_EQ(unicode.offsetByCodePoints(2, 0), 2);
1376 EXPECT_EQ(unicode.offsetByCodePoints(2, 1), 3);
1377 EXPECT_EQ(unicode.offsetByCodePoints(2, 2), 4);
1378 EXPECT_EQ(unicode.offsetByCodePoints(2, 3), 6);
1379 EXPECT_EQ(unicode.offsetByCodePoints(2, 4), 8);
1380 EXPECT_EQ(unicode.offsetByCodePoints(2, 5), 9);
1381 EXPECT_EQ(unicode.offsetByCodePoints(2, 6), 11);
1382 EXPECT_EQ(unicode.offsetByCodePoints(4, 0), 4);
1383 EXPECT_EQ(unicode.offsetByCodePoints(4, 1), 6);
1384 EXPECT_EQ(unicode.offsetByCodePoints(6, 0), 6);
1385
1386 // return the length once we reach the end of the string
1387 EXPECT_EQ(unicode.offsetByCodePoints(0, 7), 11);
1388 EXPECT_EQ(unicode.offsetByCodePoints(0, 9), 11);
1389 EXPECT_EQ(unicode.offsetByCodePoints(2, 7), 11);
1390 EXPECT_EQ(unicode.offsetByCodePoints(3, 6), 11);
1391 EXPECT_EQ(unicode.offsetByCodePoints(4, 5), 11);
1392 EXPECT_EQ(unicode.offsetByCodePoints(8, 3), 11);
1393 EXPECT_EQ(unicode.offsetByCodePoints(12, 0), 11);
1394}
1395
1396TEST_F(LargeStrTest, CodePointLengthAscii) {
1397 HandleScope scope(thread_);
1398
1399 const char* code_units = "01234567012345670";
1400
1401 Str str(&scope, runtime_->newStrFromCStr(code_units));
1402 EXPECT_TRUE(str.isLargeStr());
1403 EXPECT_EQ(str.length(), static_cast<word>(std::strlen(code_units)));
1404 EXPECT_EQ(str.codePointLength(), 17);
1405}
1406
1407TEST_F(LargeStrTest, CodePointLength) {
1408 HandleScope scope(thread_);
1409
1410 const char* code_units =
1411 "\xd7\x99\xd7\xa9 \xd7\x9c\xd7\x99 \xd7\x94\xd7\xa8\xd7\x91\xd7\x94 "
1412 "\xd7\x90\xd7\x95\xd7\xaa\xd7\x99\xd7\x95\xd7\xaa "
1413 "\xd7\xa2\xd7\x9b\xd7\xa9\xd7\x99\xd7\x95";
1414
1415 Str str(&scope, runtime_->newStrFromCStr(code_units));
1416 EXPECT_TRUE(str.isLargeStr());
1417 EXPECT_EQ(str.length(), static_cast<word>(std::strlen(code_units)));
1418 EXPECT_EQ(str.codePointLength(), 23);
1419}
1420
1421TEST_F(LargeStrTest, IncludesLargeStrChecksSubstr) {
1422 HandleScope scope(thread_);
1423 LargeStr haystack(&scope, runtime_->newStrFromCStr("abcdefghijk"));
1424 LargeStr needle(&scope, runtime_->newStrFromCStr("bcdefghi"));
1425 LargeStr not_needle(&scope, runtime_->newStrFromCStr("aaaaaaaa"));
1426
1427 EXPECT_TRUE(haystack.includes(*haystack));
1428 EXPECT_TRUE(haystack.includes(*needle));
1429 EXPECT_FALSE(haystack.includes(*not_needle));
1430}
1431
1432TEST_F(LargeStrTest, IncludesSmallStrChecksSubstr) {
1433 HandleScope scope(thread_);
1434 LargeStr haystack(&scope, runtime_->newStrFromCStr("abcdefghijkl"));
1435 SmallStr empty(&scope, Str::empty());
1436 SmallStr needle(&scope, SmallStr::fromCStr("fgh"));
1437 SmallStr not_needle(&scope, SmallStr::fromCStr("bb"));
1438
1439 EXPECT_TRUE(haystack.includes(*empty));
1440 EXPECT_TRUE(haystack.includes(*needle));
1441 EXPECT_FALSE(haystack.includes(*not_needle));
1442
1443 Str chars(&scope, runtime_->newStrFromCStr(".\\[{()*+?^$|"));
1444 Str hash(&scope, SmallStr::fromCStr("#"));
1445 EXPECT_FALSE(chars.includes(*hash));
1446}
1447
1448TEST_F(LargeStrTest, IsASCIIReturnsTrueIfAndOnlyIfAllASCII) {
1449 HandleScope scope(thread_);
1450
1451 Str ascii(&scope, runtime_->newStrFromCStr("01234567012345670"));
1452 EXPECT_TRUE(ascii.isLargeStr());
1453 EXPECT_TRUE(ascii.isASCII());
1454
1455 Str unicode(&scope, runtime_->newStrFromCStr("ascii \xd7\x99\xd7\xa9 pad"));
1456 EXPECT_TRUE(unicode.isLargeStr());
1457 EXPECT_FALSE(unicode.isASCII());
1458}
1459
1460TEST_F(LargeStrTest, OccurrencesOfWithEmptyStringReturnsZero) {
1461 HandleScope scope(thread_);
1462 Str haystack(&scope, runtime_->newStrFromCStr("hello world"));
1463 Str needle(&scope, runtime_->newStrFromCStr(""));
1464 EXPECT_EQ(haystack.occurrencesOf(*needle), 0);
1465}
1466
1467TEST_F(LargeStrTest, OccurrencesOfWithLargeStrFindsOccurrenceAtFirstChar) {
1468 HandleScope scope(thread_);
1469 Str haystack(&scope, runtime_->newStrFromCStr("hello world"));
1470 Str needle(&scope, runtime_->newStrFromCStr("hello wor"));
1471 EXPECT_EQ(haystack.occurrencesOf(*needle), 1);
1472}
1473
1474TEST_F(LargeStrTest, OccurrencesOfWithLargeStrMultipleOccurrencesFindsAll) {
1475 HandleScope scope(thread_);
1476 Str haystack(&scope, runtime_->newStrFromCStr("hello world hello world"));
1477 Str needle(&scope, runtime_->newStrFromCStr("hello world"));
1478 EXPECT_EQ(haystack.occurrencesOf(*needle), 2);
1479}
1480
1481TEST_F(LargeStrTest, OccurrencesOfWithNoOccurenceReturnsZero) {
1482 HandleScope scope(thread_);
1483 Str haystack(&scope, runtime_->newStrFromCStr("hello world"));
1484 Str needle(&scope, runtime_->newStrFromCStr("is not here"));
1485 EXPECT_EQ(haystack.occurrencesOf(*needle), 0);
1486}
1487
1488TEST_F(LargeStrTest, OccurrencesOfWithSmallStrFindsOccurrenceAtThirdChar) {
1489 HandleScope scope(thread_);
1490 Str haystack(&scope, runtime_->newStrFromCStr("hello world"));
1491 Str needle(&scope, SmallStr::fromCStr("llo"));
1492 EXPECT_EQ(haystack.occurrencesOf(*needle), 1);
1493}
1494
1495TEST_F(LargeStrTest, OccurrencesOfWithSmallStrMultipleOccurrencesFindsAll) {
1496 HandleScope scope(thread_);
1497 Str haystack(&scope, runtime_->newStrFromCStr("hello hello"));
1498 Str needle(&scope, SmallStr::fromCStr("llo"));
1499 EXPECT_EQ(haystack.occurrencesOf(*needle), 2);
1500}
1501
1502TEST_F(LargeStrTest, OccurrencesOfWithSmallStrUsesCorrectEndian) {
1503 HandleScope scope(thread_);
1504 Str haystack(&scope, runtime_->newStrFromCStr("ababababab"));
1505 Str needle(&scope, SmallStr::fromCStr("ab"));
1506 EXPECT_EQ(haystack.occurrencesOf(*needle), 5);
1507}
1508
1509TEST_F(StringTest, ReverseOffsetByCodePointsEmptyString) {
1510 HandleScope scope(thread_);
1511 Str empty(&scope, Str::empty());
1512
1513 word i = empty.length();
1514 ASSERT_EQ(0, i);
1515
1516 EXPECT_EQ(-1, empty.offsetByCodePoints(i, -1));
1517}
1518
1519TEST_F(StringTest, ReverseOffsetByCodePointsStringLength1) {
1520 HandleScope scope(thread_);
1521
1522 Str str1(&scope, runtime_->newStrFromCStr("1"));
1523 word len = str1.length();
1524 ASSERT_EQ(1, len);
1525
1526 EXPECT_EQ(1, str1.offsetByCodePoints(len, 0));
1527 EXPECT_EQ(0, str1.offsetByCodePoints(len, -1));
1528 EXPECT_EQ(-1, str1.offsetByCodePoints(len, -2));
1529}
1530
1531TEST_F(StringTest, ReverseOffsetByCodePointsStringLength3) {
1532 HandleScope scope(thread_);
1533
1534 Str str3(&scope, runtime_->newStrFromCStr("123"));
1535 word len = str3.length();
1536 ASSERT_EQ(3, len);
1537
1538 EXPECT_EQ(2, str3.offsetByCodePoints(len, -1));
1539 EXPECT_EQ(1, str3.offsetByCodePoints(len, -2));
1540 EXPECT_EQ(0, str3.offsetByCodePoints(len, -3));
1541 EXPECT_EQ(-1, str3.offsetByCodePoints(len, -4));
1542
1543 EXPECT_EQ(1, str3.offsetByCodePoints(len - 1, -1));
1544 EXPECT_EQ(0, str3.offsetByCodePoints(len - 1, -2));
1545 EXPECT_EQ(-1, str3.offsetByCodePoints(len - 1, -3));
1546 EXPECT_EQ(-1, str3.offsetByCodePoints(len - 1, -4));
1547
1548 EXPECT_EQ(0, str3.offsetByCodePoints(len - 2, -1));
1549 EXPECT_EQ(-1, str3.offsetByCodePoints(len - 2, -2));
1550 EXPECT_EQ(-1, str3.offsetByCodePoints(len - 2, -3));
1551 EXPECT_EQ(-1, str3.offsetByCodePoints(len - 2, -4));
1552}
1553
1554TEST_F(StringTest, ReverseOffsetByCodePointsUnicodeStringLength5) {
1555 HandleScope scope(thread_);
1556
1557 Str str5(&scope, runtime_->newStrFromCStr("\x41\xD7\x91\xD7\x92"));
1558 word len = str5.length();
1559 ASSERT_EQ(5, len);
1560
1561 EXPECT_EQ(3, str5.offsetByCodePoints(len, -1));
1562 EXPECT_EQ(1, str5.offsetByCodePoints(len, -2));
1563 EXPECT_EQ(0, str5.offsetByCodePoints(len, -3));
1564 EXPECT_EQ(-1, str5.offsetByCodePoints(len, -4));
1565
1566 EXPECT_EQ(1, str5.offsetByCodePoints(len - 2, -1));
1567 EXPECT_EQ(0, str5.offsetByCodePoints(len - 2, -2));
1568 EXPECT_EQ(-1, str5.offsetByCodePoints(len - 2, -3));
1569 EXPECT_EQ(-1, str5.offsetByCodePoints(len - 2, -4));
1570
1571 EXPECT_EQ(0, str5.offsetByCodePoints(len - 4, -1));
1572 EXPECT_EQ(-1, str5.offsetByCodePoints(len - 4, -2));
1573 EXPECT_EQ(-1, str5.offsetByCodePoints(len - 4, -3));
1574 EXPECT_EQ(-1, str5.offsetByCodePoints(len - 4, -4));
1575}
1576
1577TEST_F(StringTest, ToCString) {
1578 HandleScope scope(thread_);
1579
1580 Str empty(&scope, Str::empty());
1581 char* c_empty = empty.toCStr();
1582 ASSERT_NE(c_empty, nullptr);
1583 EXPECT_STREQ(c_empty, "");
1584 std::free(c_empty);
1585
1586 Str length1(&scope, runtime_->newStrFromCStr("a"));
1587 char* c_length1 = length1.toCStr();
1588 ASSERT_NE(c_length1, nullptr);
1589 EXPECT_STREQ(c_length1, "a");
1590 std::free(c_length1);
1591
1592 Str length2(&scope, runtime_->newStrFromCStr("ab"));
1593 char* c_length2 = length2.toCStr();
1594 ASSERT_NE(c_length2, nullptr);
1595 EXPECT_STREQ(c_length2, "ab");
1596 std::free(c_length2);
1597
1598 Str length10(&scope, runtime_->newStrFromCStr("1234567890"));
1599 char* c_length10 = length10.toCStr();
1600 ASSERT_NE(c_length10, nullptr);
1601 EXPECT_STREQ(c_length10, "1234567890");
1602 std::free(c_length10);
1603
1604 Str nulchar(&scope, runtime_->newStrFromCStr("wx\0yz"));
1605 char* c_nulchar = nulchar.toCStr();
1606 ASSERT_NE(c_nulchar, nullptr);
1607 EXPECT_STREQ(c_nulchar, "wx");
1608 std::free(c_nulchar);
1609}
1610
1611TEST_F(StringTest, CompareSmallStr) {
1612 HandleScope scope(thread_);
1613
1614 Str small(&scope, runtime_->newStrFromCStr("foo"));
1615 EXPECT_TRUE(small.isSmallStr());
1616
1617 EXPECT_TRUE(small.equalsCStr("foo"));
1618 // This apparently stupid test is in response to a bug where we assumed
1619 // that the c-string passed to SmallStr::equalsCStr would always
1620 // be small itself.
1621 EXPECT_FALSE(small.equalsCStr("123456789"));
1622}
1623
1624TEST_F(StringTest, CompareWithUnicode) {
1625 HandleScope scope(thread_);
1626 Str small(&scope, runtime_->newStrFromCStr(u8"hello\u2028"));
1627 EXPECT_TRUE(small.equalsCStr("hello\u2028"));
1628}
1629
1630TEST_F(ValueCellTest, SetPlaceholderRendersIsPlaceholderToReturnTrue) {
1631 HandleScope scope(thread_);
1632 ValueCell value_cell(&scope, runtime_->newValueCell());
1633 ASSERT_FALSE(value_cell.isPlaceholder());
1634 value_cell.makePlaceholder();
1635 EXPECT_TRUE(value_cell.isPlaceholder());
1636}
1637
1638TEST_F(WeakRefTest, EnqueueAndDequeue) {
1639 HandleScope scope(thread_);
1640 RawObject list = NoneType::object();
1641 Object o0(&scope, runtime_->newList());
1642 Object o1(&scope, runtime_->newList());
1643 Object o2(&scope, runtime_->newList());
1644
1645 WeakRef::enqueue(runtime_->newWeakRef(thread_, o0), &list);
1646 WeakRef::enqueue(runtime_->newWeakRef(thread_, o1), &list);
1647 WeakRef::enqueue(runtime_->newWeakRef(thread_, o2), &list);
1648
1649 WeakRef weak(&scope, WeakRef::dequeue(&list));
1650 EXPECT_EQ(weak.referent(), o0);
1651
1652 weak = WeakRef::dequeue(&list);
1653 EXPECT_EQ(weak.referent(), o1);
1654
1655 weak = WeakRef::dequeue(&list);
1656 EXPECT_EQ(weak.referent(), o2);
1657
1658 EXPECT_EQ(list, NoneType::object());
1659}
1660
1661TEST_F(WeakRefTest, SpliceQueue) {
1662 HandleScope scope(thread_);
1663 RawObject list1 = NoneType::object();
1664 RawObject list2 = NoneType::object();
1665 EXPECT_EQ(WeakRef::spliceQueue(list1, list2), NoneType::object());
1666
1667 Object none(&scope, NoneType::object());
1668 RawObject list3 = runtime_->newWeakRef(thread_, none);
1669 WeakRef::cast(list3).setLink(list3);
1670 EXPECT_EQ(WeakRef::spliceQueue(list1, list3), list3);
1671 EXPECT_EQ(WeakRef::spliceQueue(list3, list2), list3);
1672
1673 Object o0(&scope, runtime_->newDict());
1674 Object o1(&scope, runtime_->newDict());
1675 Object o2(&scope, runtime_->newDict());
1676 Object o3(&scope, runtime_->newDict());
1677
1678 WeakRef::enqueue(runtime_->newWeakRef(thread_, o0), &list1);
1679 WeakRef::enqueue(runtime_->newWeakRef(thread_, o2), &list2);
1680 WeakRef::enqueue(runtime_->newWeakRef(thread_, o1), &list1);
1681 WeakRef::enqueue(runtime_->newWeakRef(thread_, o3), &list2);
1682
1683 RawObject list = WeakRef::spliceQueue(list1, list2);
1684 WeakRef weak(&scope, WeakRef::dequeue(&list));
1685 EXPECT_EQ(weak.referent(), o0);
1686
1687 weak = WeakRef::dequeue(&list);
1688 EXPECT_EQ(weak.referent(), o1);
1689
1690 weak = WeakRef::dequeue(&list);
1691 EXPECT_EQ(weak.referent(), o2);
1692
1693 weak = WeakRef::dequeue(&list);
1694 EXPECT_EQ(weak.referent(), o3);
1695
1696 EXPECT_EQ(list, NoneType::object());
1697}
1698
1699TEST_F(ListTest, ReplaceFromWithReplacesElementsStartingAtZero) {
1700 HandleScope scope(thread_);
1701 List dst(&scope, runtime_->newList());
1702 Tuple dst_tuple(&scope, runtime_->newMutableTuple(5));
1703 dst.setItems(*dst_tuple);
1704 dst.setNumItems(5);
1705 List src(&scope, listFromRange(0, 5));
1706 dst.replaceFromWith(0, *src, 2);
1707 ASSERT_EQ(dst.numItems(), 5);
1708 EXPECT_TRUE(isIntEqualsWord(dst.at(0), 0));
1709 EXPECT_TRUE(isIntEqualsWord(dst.at(1), 1));
1710 EXPECT_EQ(dst.at(2), SmallInt::fromWord(0));
1711 EXPECT_EQ(dst.at(3), SmallInt::fromWord(0));
1712 EXPECT_EQ(dst.at(4), SmallInt::fromWord(0));
1713}
1714
1715TEST_F(ListTest, ReplaceFromWithReplacesElementsStartingInMiddle) {
1716 HandleScope scope(thread_);
1717 List dst(&scope, runtime_->newList());
1718 Tuple dst_tuple(&scope, runtime_->newMutableTuple(5));
1719 dst.setItems(*dst_tuple);
1720 dst.setNumItems(5);
1721 List src(&scope, listFromRange(0, 5));
1722 dst.replaceFromWith(1, *src, 2);
1723 ASSERT_EQ(dst.numItems(), 5);
1724 EXPECT_EQ(dst.at(0), SmallInt::fromWord(0));
1725 EXPECT_TRUE(isIntEqualsWord(dst.at(1), 0));
1726 EXPECT_TRUE(isIntEqualsWord(dst.at(2), 1));
1727 EXPECT_EQ(dst.at(3), SmallInt::fromWord(0));
1728 EXPECT_EQ(dst.at(4), SmallInt::fromWord(0));
1729}
1730
1731TEST_F(ListTest, ReplaceFromWithCopiesZeroElements) {
1732 HandleScope scope(thread_);
1733 List dst(&scope, runtime_->newList());
1734 Tuple dst_tuple(&scope, runtime_->newMutableTuple(5));
1735 dst.setItems(*dst_tuple);
1736 dst.setNumItems(5);
1737 List src(&scope, listFromRange(0, 5));
1738 dst.replaceFromWith(0, *src, 0);
1739 ASSERT_EQ(dst.numItems(), 5);
1740 EXPECT_EQ(dst.at(0), SmallInt::fromWord(0));
1741 EXPECT_EQ(dst.at(1), SmallInt::fromWord(0));
1742 EXPECT_EQ(dst.at(2), SmallInt::fromWord(0));
1743 EXPECT_EQ(dst.at(3), SmallInt::fromWord(0));
1744 EXPECT_EQ(dst.at(4), SmallInt::fromWord(0));
1745}
1746
1747TEST_F(ListTest, ReplaceFromWithCopiesEveryElementFromSrc) {
1748 HandleScope scope(thread_);
1749 List dst(&scope, runtime_->newList());
1750 Tuple dst_tuple(&scope, runtime_->newMutableTuple(5));
1751 dst.setItems(*dst_tuple);
1752 dst.setNumItems(5);
1753 List src(&scope, listFromRange(0, 5));
1754 dst.replaceFromWith(0, *src, 5);
1755 ASSERT_EQ(dst.numItems(), 5);
1756 EXPECT_TRUE(isIntEqualsWord(dst.at(0), 0));
1757 EXPECT_TRUE(isIntEqualsWord(dst.at(1), 1));
1758 EXPECT_TRUE(isIntEqualsWord(dst.at(2), 2));
1759 EXPECT_TRUE(isIntEqualsWord(dst.at(3), 3));
1760 EXPECT_TRUE(isIntEqualsWord(dst.at(4), 4));
1761}
1762
1763TEST_F(ListTest, ReplaceFromWithStartAtReplacesElementsStartingAtSrcStart) {
1764 HandleScope scope(thread_);
1765 List dst(&scope, runtime_->newList());
1766 Tuple dst_tuple(&scope, runtime_->newMutableTuple(5));
1767 dst.setItems(*dst_tuple);
1768 dst.setNumItems(5);
1769 List src(&scope, listFromRange(0, 5));
1770 dst.replaceFromWithStartAt(0, *src, 2, 2);
1771 ASSERT_EQ(dst.numItems(), 5);
1772 EXPECT_TRUE(isIntEqualsWord(dst.at(0), 2));
1773 EXPECT_TRUE(isIntEqualsWord(dst.at(1), 3));
1774 EXPECT_EQ(dst.at(2), SmallInt::fromWord(0));
1775 EXPECT_EQ(dst.at(3), SmallInt::fromWord(0));
1776 EXPECT_EQ(dst.at(4), SmallInt::fromWord(0));
1777}
1778
1779TEST_F(ListTest, ReplaceFromWithStartAtWithSelfNoop) {
1780 HandleScope scope(thread_);
1781 List dst(&scope, listFromRange(0, 5));
1782 dst.replaceFromWithStartAt(0, *dst, 2, 0);
1783 EXPECT_PYLIST_EQ(dst, {0, 1, 2, 3, 4});
1784}
1785
1786TEST_F(ListTest, ReplaceFromWithStartAtWithSelfBackward) {
1787 HandleScope scope(thread_);
1788 List dst(&scope, listFromRange(0, 5));
1789 dst.replaceFromWithStartAt(0, *dst, 2, 2);
1790 EXPECT_PYLIST_EQ(dst, {2, 3, 2, 3, 4});
1791}
1792
1793TEST_F(ListTest, ReplaceFromWithStartAtWithSelfForward) {
1794 HandleScope scope(thread_);
1795 List dst(&scope, listFromRange(0, 5));
1796 dst.replaceFromWithStartAt(2, *dst, 2, 0);
1797 EXPECT_PYLIST_EQ(dst, {0, 1, 0, 1, 4});
1798}
1799
1800TEST_F(ListTest, SwapSwapsElementsAtIndices) {
1801 HandleScope scope(thread_);
1802 List src(&scope, listFromRange(0, 5));
1803 EXPECT_PYLIST_EQ(src, {0, 1, 2, 3, 4});
1804 src.swap(1, 3);
1805 EXPECT_PYLIST_EQ(src, {0, 3, 2, 1, 4});
1806}
1807
1808TEST_F(MutableTupleTest, NoneFillTupleFillsTupleWithNone) {
1809 HandleScope scope(thread_);
1810 MutableTuple tuple(&scope, runtime_->newMutableTuple(3));
1811 tuple.atPut(0, SmallInt::fromWord(0));
1812 tuple.atPut(1, SmallInt::fromWord(1));
1813 tuple.atPut(2, SmallInt::fromWord(2));
1814 tuple.fill(NoneType::object());
1815 EXPECT_EQ(tuple.at(0), NoneType::object());
1816 EXPECT_EQ(tuple.at(1), NoneType::object());
1817 EXPECT_EQ(tuple.at(2), NoneType::object());
1818}
1819
1820TEST_F(MutableTupleTest, ReplaceFromWithReplacesElementsStartingAtZero) {
1821 HandleScope scope(thread_);
1822 MutableTuple dst(&scope, runtime_->newMutableTuple(5));
1823 List src(&scope, listFromRange(0, 5));
1824 Tuple src_items(&scope, src.items());
1825 dst.replaceFromWith(0, *src_items, 2);
1826 EXPECT_TRUE(isIntEqualsWord(dst.at(0), 0));
1827 EXPECT_TRUE(isIntEqualsWord(dst.at(1), 1));
1828 EXPECT_EQ(dst.at(2), SmallInt::fromWord(0));
1829 EXPECT_EQ(dst.at(3), SmallInt::fromWord(0));
1830 EXPECT_EQ(dst.at(4), SmallInt::fromWord(0));
1831}
1832
1833TEST_F(MutableTupleTest, ReplaceFromWithReplacesElementsStartingInMiddle) {
1834 HandleScope scope(thread_);
1835 MutableTuple dst(&scope, runtime_->newMutableTuple(5));
1836 List src(&scope, listFromRange(0, 5));
1837 Tuple src_items(&scope, src.items());
1838 dst.replaceFromWith(1, *src_items, 2);
1839 EXPECT_EQ(dst.at(0), SmallInt::fromWord(0));
1840 EXPECT_TRUE(isIntEqualsWord(dst.at(1), 0));
1841 EXPECT_TRUE(isIntEqualsWord(dst.at(2), 1));
1842 EXPECT_EQ(dst.at(3), SmallInt::fromWord(0));
1843 EXPECT_EQ(dst.at(4), SmallInt::fromWord(0));
1844}
1845
1846TEST_F(MutableTupleTest, ReplaceFromWithCopiesZeroElements) {
1847 HandleScope scope(thread_);
1848 MutableTuple dst(&scope, runtime_->newMutableTuple(5));
1849 List src(&scope, listFromRange(0, 5));
1850 Tuple src_items(&scope, src.items());
1851 dst.replaceFromWith(0, *src_items, 0);
1852 EXPECT_EQ(dst.at(0), SmallInt::fromWord(0));
1853 EXPECT_EQ(dst.at(1), SmallInt::fromWord(0));
1854 EXPECT_EQ(dst.at(2), SmallInt::fromWord(0));
1855 EXPECT_EQ(dst.at(3), SmallInt::fromWord(0));
1856 EXPECT_EQ(dst.at(4), SmallInt::fromWord(0));
1857}
1858
1859TEST_F(MutableTupleTest, ReplaceFromWithCopiesEveryElementFromSrc) {
1860 HandleScope scope(thread_);
1861 MutableTuple dst(&scope, runtime_->newMutableTuple(5));
1862 List src(&scope, listFromRange(0, 5));
1863 Tuple src_items(&scope, src.items());
1864 dst.replaceFromWith(0, *src_items, 5);
1865 EXPECT_TRUE(isIntEqualsWord(dst.at(0), 0));
1866 EXPECT_TRUE(isIntEqualsWord(dst.at(1), 1));
1867 EXPECT_TRUE(isIntEqualsWord(dst.at(2), 2));
1868 EXPECT_TRUE(isIntEqualsWord(dst.at(3), 3));
1869 EXPECT_TRUE(isIntEqualsWord(dst.at(4), 4));
1870}
1871
1872TEST_F(MutableTupleTest, ReplaceFromWithStartAtWithSelfNoop) {
1873 HandleScope scope(thread_);
1874 List dst_list(&scope, listFromRange(0, 5));
1875 MutableTuple dst(&scope, dst_list.items());
1876 dst.replaceFromWithStartAt(0, *dst, 2, 0);
1877 EXPECT_PYLIST_EQ(dst_list, {0, 1, 2, 3, 4});
1878}
1879
1880TEST_F(MutableTupleTest, ReplaceFromWithStartAtWithSelfBackward) {
1881 HandleScope scope(thread_);
1882 List dst_list(&scope, listFromRange(0, 5));
1883 MutableTuple dst(&scope, dst_list.items());
1884 dst.replaceFromWithStartAt(0, *dst, 2, 2);
1885 EXPECT_PYLIST_EQ(dst_list, {2, 3, 2, 3, 4});
1886}
1887
1888TEST_F(MutableTupleTest, ReplaceFromWithStartAtWithSelfForward) {
1889 HandleScope scope(thread_);
1890 List dst_list(&scope, listFromRange(0, 5));
1891 MutableTuple dst(&scope, dst_list.items());
1892 dst.replaceFromWithStartAt(2, *dst, 2, 0);
1893 EXPECT_PYLIST_EQ(dst_list, {0, 1, 0, 1, 4});
1894}
1895
1896TEST_F(MutableTupleTest,
1897 ReplaceFromWithStartAtReplacesElementsStartingAtSrcStart) {
1898 HandleScope scope(thread_);
1899 MutableTuple dst(&scope, runtime_->newMutableTuple(5));
1900 List src_list(&scope, listFromRange(0, 5));
1901 Tuple src(&scope, src_list.items());
1902 dst.replaceFromWithStartAt(0, *src, 2, 2);
1903 EXPECT_TRUE(isIntEqualsWord(dst.at(0), 2));
1904 EXPECT_TRUE(isIntEqualsWord(dst.at(1), 3));
1905 EXPECT_EQ(dst.at(2), SmallInt::fromWord(0));
1906 EXPECT_EQ(dst.at(3), SmallInt::fromWord(0));
1907 EXPECT_EQ(dst.at(4), SmallInt::fromWord(0));
1908}
1909
1910TEST_F(MutableTupleTest, SwapSwapsElementsAtIndices) {
1911 HandleScope scope(thread_);
1912 List src_list(&scope, listFromRange(0, 5));
1913 MutableTuple src(&scope, src_list.items());
1914 EXPECT_PYLIST_EQ(src_list, {0, 1, 2, 3, 4});
1915 src.swap(1, 3);
1916 EXPECT_PYLIST_EQ(src_list, {0, 3, 2, 1, 4});
1917}
1918
1919TEST(ErrorTest, ErrorIsError) {
1920 EXPECT_TRUE(Error::error().isError());
1921
1922 EXPECT_TRUE(Error::exception().isError());
1923 EXPECT_TRUE(Error::exception().isErrorException());
1924
1925 EXPECT_TRUE(Error::notFound().isError());
1926 EXPECT_TRUE(Error::notFound().isErrorNotFound());
1927
1928 EXPECT_TRUE(Error::noMoreItems().isError());
1929 EXPECT_TRUE(Error::noMoreItems().isErrorNoMoreItems());
1930
1931 EXPECT_TRUE(Error::outOfMemory().isError());
1932 EXPECT_TRUE(Error::outOfMemory().isErrorOutOfMemory());
1933
1934 EXPECT_TRUE(Error::outOfBounds().isError());
1935 EXPECT_TRUE(Error::outOfBounds().isErrorOutOfBounds());
1936}
1937
1938TEST(ErrorTest, ErrorHasCorrectKind) {
1939 EXPECT_EQ(Error::error().kind(), ErrorKind::kNone);
1940 EXPECT_EQ(Error::exception().kind(), ErrorKind::kException);
1941 EXPECT_EQ(Error::notFound().kind(), ErrorKind::kNotFound);
1942 EXPECT_EQ(Error::noMoreItems().kind(), ErrorKind::kNoMoreItems);
1943 EXPECT_EQ(Error::outOfMemory().kind(), ErrorKind::kOutOfMemory);
1944 EXPECT_EQ(Error::outOfBounds().kind(), ErrorKind::kOutOfBounds);
1945}
1946
1947} // namespace testing
1948} // namespace py