blob: 049e4dab9013b3d3a8b81a24ff7994848f78d59c [file] [edit]
[case testLibrtVecsNestedInterpreted_librt]
# Test cases for nested vecs, using generic operations (simulates use from interpreted code).
import sys
from typing import Any
import typing
import librt.vecs
import mypy_extensions
from testutil import assertRaises, is_gil_disabled, is_64_bit_platform
vec: Any = librt.vecs.vec
append: Any = librt.vecs.append
remove: Any = librt.vecs.remove
pop: Any = librt.vecs.pop
extend: Any = librt.vecs.extend
getsizeof: Any = getattr(sys, "getsizeof")
i64: Any = mypy_extensions.i64
# Work around test stub limitations
Optional: Any = getattr(getattr(sys, "modules")["typing"], "Optional")
def test_vec_indexing() -> None:
assert type(vec[vec[str]]) is type(vec[str])
assert type(vec[vec[Optional[str]]]) is type(vec[str])
assert type(vec[vec[i64]]) is type(vec[str])
assert type(vec[vec[vec[vec[vec[vec[str]]]]]]) is type(vec[str])
with assertRaises(TypeError):
vec[Optional[vec[str]]]
with assertRaises(TypeError):
vec[Optional[vec[Optional[str]]]]
def test_type_str() -> None:
assert str(vec[Optional[str]]) == "<class_proxy 'vec[str | None]'>"
assert str(vec[vec[str]]) == "<class_proxy 'vec[vec[str]]'>"
assert str(vec[vec[i64]]) == "<class_proxy 'vec[vec[i64]]'>"
assert str(vec[vec[vec[vec[vec[str]]]]]) == "<class_proxy 'vec[vec[vec[vec[vec[str]]]]]'>"
assert str(
vec[vec[vec[Optional[str]]]]) == "<class_proxy 'vec[vec[vec[str | None]]]'>"
def test_construct_empty_nested() -> None:
v = vec[vec[str]]()
assert len(v) == 0
v2 = vec[vec[vec[vec[vec[str]]]]]()
assert len(v2) == 0
v3 = vec[vec[i64]]()
assert len(v3) == 0
def test_construct_empty_nested_optional() -> None:
v = vec[vec[Optional[str]]]()
assert len(v) == 0
def test_construct_from_initializer_nested() -> None:
v = vec[vec[str]]([vec[str](['xyz'])])
assert len(v) == 1
assert v[0][0] == 'xyz'
with assertRaises(TypeError):
vec[str](1)
with assertRaises(TypeError):
vec[str]([1])
with assertRaises(TypeError):
vec[str]([vec[bytes]()])
def test_construct_from_tuple_nested() -> None:
v = vec[vec[str]](())
assert len(v) == 0
v = vec[vec[str]]((vec[str](['a']), vec[str](['b', 'c'])))
assert len(v) == 2
assert v[0][0] == 'a'
assert v[1][0] == 'b'
assert v[1][1] == 'c'
with assertRaises(TypeError):
vec[vec[str]]((vec[str](), 'x'))
def test_isinstance() -> None:
assert isinstance(vec[vec[str]](), vec)
assert isinstance(vec[vec[Optional[str]]](), vec)
def test_repr() -> None:
assert str(vec[vec[str]]()) == "vec[vec[str]]([])"
assert str(vec[vec[Optional[str]]]()) == "vec[vec[str | None]]([])"
def test_append_nested() -> None:
v = vec[vec[str]]()
vv = append(vec[str](), '1')
v = append(v, vv)
assert str(v) == "vec[vec[str]]([['1']])"
for n in range(2, 10):
vv = append(vec[str](), str(n))
v = append(v, vv)
assert str(v) == (
"vec[vec[str]]([['1'], ['2'], ['3'], ['4'], ['5'], ['6'], ['7'], ['8'], ['9']])"
)
def test_append_i64() -> None:
v = vec[vec[i64]]()
vv = append(vec[i64](), 1)
v = append(v, vv)
assert str(v) == "vec[vec[i64]]([[1]])"
for n in range(2, 10):
vv = append(vec[i64](), n)
v = append(v, vv)
assert str(v) == (
"vec[vec[i64]]([[1], [2], [3], [4], [5], [6], [7], [8], [9]])"
)
def test_append_nested_optional() -> None:
v = vec[vec[Optional[str]]]()
v = append(v, vec[Optional[str]]())
v = append(v, vec[Optional[str]](['x', None]))
assert str(v) == "vec[vec[str | None]]([[], ['x', None]])"
def test_size() -> None:
# Only test on 64-bit, non-free-threading builds
if not is_gil_disabled() and is_64_bit_platform():
v = vec[vec[str]]()
assert getsizeof(v) == 48
v = append(v, vec[str]())
assert getsizeof(v) == 48
def test_get_item() -> None:
v = append(vec[vec[str]](), append(vec[str](), 'x'))
assert repr(v[0]) == "vec[str](['x'])"
v = append(v, append(vec[str](), 'y'))
assert repr(v[0]) == "vec[str](['x'])"
assert repr(v[1]) == "vec[str](['y'])"
vv = append(vec[vec[Optional[str]]](), vec[Optional[str]]())
assert vv[0] == vec[Optional[str]]()
def test_get_item_error() -> None:
v = append(vec[vec[str]](), vec[str](['1']))
v = append(v, vec[str](['2']))
v = append(v, vec[str](['3']))
with assertRaises(IndexError):
v[3]
with assertRaises(IndexError):
v[4]
n = 2 ** 100
with assertRaises(IndexError):
v[n]
def test_get_item_negative() -> None:
v = vec[vec[str]]([vec[str](['2']), vec[str](['5']), vec[str](['7'])])
assert v[-1] == vec[str](['7'])
assert v[-2] == vec[str](['5'])
assert v[-3] == vec[str](['2'])
with assertRaises(IndexError):
v[-4]
with assertRaises(IndexError):
v[-2**62]
def test_len() -> None:
v = vec[vec[str]]()
assert len(v) == 0
v = append(v, vec[str](['1']))
assert len(v) == 1
v = append(v, vec[str]())
assert len(v) == 2
for i in range(100):
v = append(v, vec[str](['i']))
assert len(v) == i + 3
def test_set_item() -> None:
v = vec[vec[str]]()
v = append(v, vec[str](['1']))
v = append(v, vec[str](['2']))
v[0] = vec[str](['3'])
assert v[0] == vec[str](['3'])
assert v[1] == vec[str](['2'])
v[1] = vec[str](['5'])
assert v[0] == vec[str](['3'])
assert v[1] == vec[str](['5'])
def test_set_item_error_nested() -> None:
v = append(vec[vec[str]](), vec[str]())
v = append(v, vec[str]())
v = append(v, vec[str]())
with assertRaises(IndexError):
v[3] = vec[str]()
with assertRaises(TypeError):
v[0] = 'x'
with assertRaises(TypeError):
v[0] = vec[vec[str]]()
with assertRaises(TypeError):
v[0] = vec[Optional[str]]()
assert repr(v[0]) == 'vec[str]([])'
def test_set_item_negative() -> None:
v = vec[vec[str]]()
v = append(v, vec[str](['1']))
v = append(v, vec[str](['2']))
v[-2] = vec[str](['3'])
assert v[0] == vec[str](['3'])
assert v[1] == vec[str](['2'])
v[-1] = vec[str](['5'])
assert v[0] == vec[str](['3'])
assert v[1] == vec[str](['5'])
with assertRaises(IndexError):
v[-3] = vec[str](['5'])
def test_equality() -> None:
assert_eq(vec[vec[str]](), vec[vec[str]]())
assert_eq(vec[vec[str]]([vec[str](['x'])]), vec[vec[str]]([vec[str](['x'])]))
assert_neq(vec[vec[str]]([vec[str](['x'])]), vec[vec[str]]())
assert_neq(vec[vec[str]]([vec[str](['x'])]), vec[vec[str]]([vec[str](['y'])]))
def test_equality_different_types() -> None:
assert_neq(vec[vec[str]](), vec[str]())
assert_neq(vec[vec[str]](), vec[vec[vec[str]]]())
assert_neq(vec[vec[Optional[str]]](), vec[vec[str]]())
def assert_eq(x: object, y: object) -> None:
assert x == y
assert y == x
b = x != y
assert not b
b = y != x
assert not b
def assert_neq(x: object, y: object) -> None:
assert x != y
assert y != x
b = x == y
assert not b
b = y == x
assert not b
def test_slicing() -> None:
v = vec[vec[str]](vec[str]([str(i)]) for i in range(5))
assert v[1:4] == vec[vec[str]]([v[1], v[2], v[3]])
assert v[2:-1] == vec[vec[str]]([v[2], v[3]])
assert v[-2:-1] == vec[vec[str]]([v[3]])
assert v[1:] == vec[vec[str]]([v[1], v[2], v[3], v[4]])
assert v[:-1] == vec[vec[str]]([v[0], v[1], v[2], v[3]])
assert v[:] == v
assert v[:] is not v
assert v[0:5] ==v
assert v[0:5] is not v
assert v[2:100] == vec[vec[str]]([v[2], v[3], v[4]])
assert v[-100:2] == vec[vec[str]]([v[0], v[1]])
assert v[5:100] == vec[vec[str]]([])
assert v[50:100] == vec[vec[str]]([])
assert v[-100:-50] == vec[vec[str]]([])
def test_slicing_with_step() -> None:
v = vec[vec[str]](vec[str]([str(i)]) for i in range(10))
assert v[1:5:2] == vec[vec[str]]([v[1], v[3]])
assert v[1:6:2] == vec[vec[str]]([v[1], v[3], v[5]])
assert v[5:1:-2] == vec[vec[str]]([v[5], v[3]])
assert v[6:1:-2] == vec[vec[str]]([v[6], v[4], v[2]])
v = vec[vec[str]](vec[str]([str(i)]) for i in range(5))
assert v[::-1] == vec[vec[str]]([v[4], v[3], v[2], v[1], v[0]])
with assertRaises(ValueError):
v[1:3:0]
def test_slicing_with_different_item_types() -> None:
v = vec[Optional[str]](['x', None, 'y'])
assert v[1:] == vec[Optional[str]]([None, 'y'])
vv = vec[vec[str]]([vec[str](['x']), vec[str](['y'])])
assert vv[1:] == vec[vec[str]]([vec[str](['y'])])
def test_remove() -> None:
a = ['4x', '7x', '9x']
vv = [vec[str]([s]) for s in a]
for i, s in enumerate(a):
v = vec[vec[str]](vv)
v = remove(v, vv[i])
assert v == vec[vec[str]]([j for j in vv if j != vv[i]])
v = vec[vec[str]](vv)
# Make sure we have a different object identity
v = remove(v, vec[str]([a[i]]))
assert v == vec[vec[str]]([j for j in vv if j != vv[i]])
v = vec[vec[str]](vv)
v = remove(v, vv[0])
v = remove(v, vv[1])
v = remove(v, vv[2])
assert v == vec[vec[str]]()
with assertRaises(ValueError):
remove(v, vec[str](['4']))
v = append(v, vec[str](['5']))
with assertRaises(ValueError):
remove(v, vec[str](['7']))
v = remove(v, vec[str](['5']))
assert len(v) == 0
v = v0 = vec[vec[str]]([vec[str](['x']) for _ in range(3)])
v = remove(v, vec[str](['x']))
assert v == v0[1:]
v = remove(v, vec[str](['x']))
assert v == v0[2:]
v = remove(v, vec[str](['x']))
assert v == vec[vec[str]]()
vb: Any = vec[bytes]([b'x'])
with assertRaises(TypeError):
remove(v, vb)
def test_pop_last() -> None:
v = vec[vec[str]]([vec[str](['4']), vec[str](['5']), vec[str](['9'])])
v, item = pop(v)
assert item == vec[str](['9'])
assert v == vec[vec[str]]([vec[str](['4']), vec[str](['5'])])
v, item = pop(v)
assert item == vec[str](['5'])
assert v == vec[vec[str]]([vec[str](['4'])])
v, item = pop(v)
assert item == vec[str](['4'])
assert v == vec[vec[str]]()
with assertRaises(IndexError):
pop(v)
def test_pop_index() -> None:
v = vec[vec[str]](vec[str]([s]) for s in ['4', '7', '9', '15', '22'])
v, item = pop(v, 0)
assert item == vec[str](['4'])
assert v == vec[vec[str]](vec[str]([s]) for s in ['7', '9', '15', '22'])
v, item = pop(v, -1)
assert item == vec[str](['22'])
assert v == vec[vec[str]](vec[str]([s]) for s in ['7', '9', '15'])
v, item = pop(v, 1)
assert item == vec[str](['9'])
assert v == vec[vec[str]](vec[str]([s]) for s in ['7', '15'])
with assertRaises(IndexError):
pop(v, 2)
with assertRaises(IndexError):
pop(v, -3)
v, item = pop(v, -2)
assert item == vec[str](['7'])
assert v == vec[vec[str]]([vec[str](['15'])])
v, item = pop(v, 0)
assert item == vec[str](['15'])
assert v == vec[vec[str]]()
def test_iteration() -> None:
# Test empty nested vec iteration
for x in vec[vec[str]]():
assert False
# Test single item iteration
a = []
for x in vec[vec[str]]([vec[str](['a'])]):
a.append(x)
assert a == [vec[str](['a'])]
# Test multiple items iteration
a = []
for x in vec[vec[str]]([vec[str](['a']), vec[str](['b', 'c']), vec[str]()]):
a.append(x)
assert a == [vec[str](['a']), vec[str](['b', 'c']), vec[str]()]
# Test iteration with vec[vec[i64]]
a = []
for x in vec[vec[i64]]([vec[i64]([1, 2]), vec[i64]([3])]):
a.append(x)
assert a == [vec[i64]([1, 2]), vec[i64]([3])]
def test_iteration_nested_loop() -> None:
# Test nested iteration over same vec
v = vec[vec[str]]([vec[str](['a']), vec[str](['b'])])
a = []
for x in v:
for y in v:
a.append((x, y))
assert a == [
(vec[str](['a']), vec[str](['a'])),
(vec[str](['a']), vec[str](['b'])),
(vec[str](['b']), vec[str](['a'])),
(vec[str](['b']), vec[str](['b'])),
]
def test_iteration_deeply_nested() -> None:
# Test vec[vec[vec[str]]] iteration
vvv = vec[vec[vec[str]]]([
vec[vec[str]]([vec[str](['a'])]),
vec[vec[str]]([vec[str](['b']), vec[str](['c'])])
])
a = []
for x in vvv:
a.append(x)
assert len(a) == 2
assert a[0] == vec[vec[str]]([vec[str](['a'])])
assert a[1] == vec[vec[str]]([vec[str](['b']), vec[str](['c'])])
def test_iterator_protocol() -> None:
# Test iter() and next() functions explicitly
v = vec[vec[str]]([vec[str](['a']), vec[str](['b']), vec[str](['c'])])
it = iter(v)
assert next(it) == vec[str](['a'])
assert next(it) == vec[str](['b'])
assert next(it) == vec[str](['c'])
with assertRaises(StopIteration):
next(it)
# Test multiple iterators on same vec
v = vec[vec[i64]]([vec[i64]([1]), vec[i64]([2])])
it1 = iter(v)
it2 = iter(v)
assert next(it1) == vec[i64]([1])
assert next(it2) == vec[i64]([1])
assert next(it1) == vec[i64]([2])
assert next(it2) == vec[i64]([2])
# Test empty vec iterator
it = iter(vec[vec[str]]())
with assertRaises(StopIteration):
next(it)
def test_iterator_length_hint() -> None:
v = vec[vec[str]]([vec[str](['a']), vec[str](['b']), vec[str](['c']), vec[str](['d']), vec[str](['e'])])
it = iter(v)
op: Any = getattr(sys, "modules")["operator"]
length_hint = op.length_hint
assert length_hint(it) == 5
next(it)
assert length_hint(it) == 4
next(it)
next(it)
assert length_hint(it) == 2
next(it)
next(it)
assert length_hint(it) == 0
def test_contains() -> None:
v1 = vec[str](['a'])
v2 = vec[str](['b'])
v3 = vec[str](['c'])
v = vec[vec[str]]([v1, v2, v3])
assert v1 in v
assert v2 in v
assert v3 in v
assert vec[str]([]) not in v
assert vec[str](['d']) not in v
def test_contains_empty() -> None:
v = vec[vec[str]]()
assert vec[str]([]) not in v
assert vec[str](['x']) not in v
def test_contains_equality() -> None:
# Test that equality is used, not just identity
v = vec[vec[str]]([vec[str](['x', 'y'])])
assert vec[str](['x', 'y']) in v
assert vec[str](['x']) not in v
assert vec[str](['y']) not in v
def test_contains_nested_i64() -> None:
v = vec[vec[i64]]([vec[i64]([1, 2]), vec[i64]([3])])
assert vec[i64]([1, 2]) in v
assert vec[i64]([3]) in v
assert vec[i64]([1]) not in v
assert vec[i64]([]) not in v
def test_contains_wrong_type() -> None:
v: Any = vec[vec[str]]([vec[str](['x'])])
assert 'x' not in v
assert 123 not in v
assert None not in v
assert [] not in v
def test_contains_deeply_nested() -> None:
inner = vec[vec[str]]([vec[str](['a'])])
v = vec[vec[vec[str]]]([inner])
assert inner in v
assert vec[vec[str]]([vec[str](['a'])]) in v
assert vec[vec[str]]([vec[str](['b'])]) not in v
assert vec[vec[str]]() not in v
def test_append_with_alias() -> None:
v = vec[vec[i64]]()
v = append(v, vec[i64]([1, 2, 3]))
alias = v
v = append(v, vec[i64]([4, 5]))
v = append(v, vec[i64]([6]))
v = append(v, vec[i64]([7]))
assert alias[0] == vec[i64]([1, 2, 3])
assert len(alias) == 1
assert v[0] == vec[i64]([1, 2, 3])
assert len(v) == 4
def test_cap_basic() -> None:
v = vec[vec[str]](capacity=3)
assert len(v) == 0
assert v == vec[vec[str]]()
v = vec[vec[str]](capacity=0)
assert len(v) == 0
v = vec[vec[str]]([vec[str](['a']), vec[str](['b'])], capacity=3)
assert v[0] == vec[str](['a'])
v = vec[vec[str]]([vec[str](['x'])], capacity=0)
assert v == vec[vec[str]]([vec[str](['x'])])
v = vec[vec[str]]([vec[str](['a']), vec[str](['b']), vec[str](['c'])], capacity=1)
assert len(v) == 3
def test_cap_negative() -> None:
with assertRaises(ValueError):
vec[vec[str]](capacity=-1)
with assertRaises(ValueError):
vec[vec[str]]([vec[str]()], capacity=-1)
def test_cap_buffer_reuse() -> None:
v = vec[vec[str]](capacity=3)
old = v
v = append(v, vec[str](['a']))
v = append(v, vec[str](['b']))
v = append(v, vec[str](['c']))
assert len(v) == 3
old = append(old, vec[str](['Q']))
assert v[0] == vec[str](['Q'])
v = vec[vec[str]]([vec[str](['a']), vec[str](['b'])], capacity=3)
old = v
v = append(v, vec[str](['c']))
v[0] = vec[str](['z'])
assert old[0] == vec[str](['z'])
def test_cap_reallocation() -> None:
v = vec[vec[str]]([vec[str](['a']), vec[str](['b'])], capacity=2)
old = v
v = append(v, vec[str](['c']))
old = append(old, vec[str](['Q']))
assert v[0] == vec[str](['a'])
v = vec[vec[str]]([vec[str](['a']), vec[str](['b']), vec[str](['c'])], capacity=3)
old = v
v = append(v, vec[str](['d']))
v[0] = vec[str](['z'])
assert old[0] == vec[str](['a'])
assert old[2] == vec[str](['c'])
def test_extend_from_list() -> None:
v1 = vec[str](['a'])
v2 = vec[str](['b'])
v = vec[vec[str]]([v1])
v = extend(v, [v2])
assert v == vec[vec[str]]([v1, v2])
def test_extend_empty_vec() -> None:
v = vec[vec[i64]]()
v = extend(v, [vec[i64]([1, 2])])
assert v == vec[vec[i64]]([vec[i64]([1, 2])])
def test_extend_with_empty_iterable() -> None:
v = vec[vec[str]]([vec[str](['x'])])
v = extend(v, [])
assert v == vec[vec[str]]([vec[str](['x'])])
def test_extend_shared_buffer_after_pop() -> None:
v0 = vec[vec[str]]([vec[str](['a']), vec[str](['b']), vec[str](['c'])])
v1, _ = pop(v0)
# v1 and v0 share a buffer
v = extend(v1, vec[vec[str]]([vec[str](['d']), vec[str](['e']), vec[str](['f'])]))
assert len(v) == 5
assert v[0] == vec[str](['a'])
assert v[4] == vec[str](['f'])
# v0 must not be corrupted
assert v0 == vec[vec[str]]([vec[str](['a']), vec[str](['b']), vec[str](['c'])])