| -- Test cases for vec[t] where t is a boxed, non-vec type (PyObject *). | |
| -- Also tests for vec[t | None], which uses the same representation. | |
| [case testVecTBasicOps_librt] | |
| from typing import Final, Any, Iterable, Optional, Tuple | |
| from mypy_extensions import i64 | |
| from librt.vecs import vec, append, extend, remove, pop | |
| from testutil import assertRaises | |
| def test_create_empty() -> None: | |
| v = vec[str]() | |
| assert len(v) == 0 | |
| v2 = vec[Optional[str]]() | |
| assert len(v2) == 0 | |
| def test_create_from_list_and_get_item() -> None: | |
| v = vec[str]([]) | |
| assert len(v) == 0 | |
| v = vec[str](["xyz", "0" + str(), str(), "foo"]) | |
| assert len(v) == 4 | |
| assert v[0] == "xyz" | |
| assert v[1] == "0" | |
| assert v[2] == "" | |
| assert v[3] == "foo" | |
| v = vec[str](["1", "2", "3", "4", "5", "6", "7", "8", "9"]) | |
| assert len(v) == 9 | |
| for i in range(i64(9)): | |
| assert v[i] == str(i + 1) | |
| def test_create_optional_and_get_item() -> None: | |
| v = vec[Optional[str]](["xyz", None]) | |
| assert len(v) == 2 | |
| assert v[0] == "xyz" | |
| assert v[1] is None | |
| def test_append() -> None: | |
| v = vec[str]() | |
| v = append(v, str() + "3") | |
| assert len(v) == 1 | |
| x = "xyz" + str() | |
| v = append(v, x) | |
| assert len(v) == 2 | |
| assert v[0] == "3" | |
| assert v[1] == "xyz" | |
| v = vec[str]() | |
| for i in range(1024): | |
| v = append(v, str(i * 3)) | |
| assert len(v) == 1024 | |
| for i in range(1024): | |
| assert v[i] == str(i * 3) | |
| def test_get_item() -> None: | |
| v = vec[str](["3", "4"]) | |
| x: i64 = int() | |
| assert v[x] == "3" | |
| assert v[int()] == "3" | |
| x += 1 | |
| assert v[x] == "4" | |
| assert v[int() + 1] == "4" | |
| with assertRaises(IndexError): | |
| v[x + 1] | |
| with assertRaises(IndexError): | |
| v[2] | |
| with assertRaises(IndexError): | |
| v[2**63 - 1] | |
| def test_set_item() -> None: | |
| v = vec[str](["3", "4"]) | |
| v[0] = "0" | |
| assert v[0] == "0" | |
| x: i64 = int() | |
| v[x] = "4" | |
| assert v[x] == "4" | |
| v[int()] = "5" | |
| assert v[int()] == "5" | |
| x += 1 | |
| v[x] = "-5" | |
| assert v[x] == "-5" | |
| v[1 + int()] = "xyz" | |
| assert v[1] == "xyz" | |
| with assertRaises(IndexError): | |
| v[1 + x] = "6" | |
| with assertRaises(IndexError): | |
| v[2 + int()] = "6" | |
| def test_set_item_optional() -> None: | |
| v = vec[Optional[str]](["3", None]) | |
| v[1] = str() + "a" | |
| assert v[1] == "a" | |
| v[0] = None | |
| assert v[0] is None | |
| def test_box_and_unbox() -> None: | |
| v = vec[str](["3", "5"]) | |
| o: Any = v | |
| assert len(o) == 2 | |
| assert o[0] == "3" | |
| assert o[1] == "5" | |
| o[1] = "6" | |
| v2: vec[str] = o | |
| assert len(v2) == 2 | |
| assert v2[0] == "3" | |
| assert v2[1] == "6" | |
| o2: Any = None | |
| with assertRaises(TypeError, "vec[str] object expected; got None"): | |
| v2 = o2 | |
| o3: Any = vec[bytes]([]) | |
| with assertRaises(TypeError, "vec[str] object expected; got vec"): | |
| v2 = o3 | |
| def test_box_and_unbox_optional() -> None: | |
| v = vec[Optional[str]](["3", "4"]) | |
| o: Any = v | |
| o[0] = None | |
| v = o | |
| assert v == vec[Optional[str]]([None, "4"]) | |
| v2 = vec[str](["4"]) | |
| o2: Any = v2 | |
| o2[0] = "5" | |
| v2 = o2 | |
| assert v2 == vec[str](["5"]) | |
| o3: Any = vec[str]() | |
| with assertRaises(TypeError, "vec[str | None] object expected; got vec"): | |
| v = o3 | |
| o4: Any = vec[Optional[str]](["3"]) | |
| with assertRaises(TypeError, "vec[str] object expected; got vec"): | |
| v2 = o4 | |
| def test_construct_from_list_multiply() -> None: | |
| for i in range(50): | |
| v = vec[str]([str(i + 1)] * i) | |
| assert len(v) == i | |
| for j in range(i): | |
| assert v[j] == str(i + 1) | |
| for i in range(50): | |
| v = vec[str](i * [str(i - 1)]) | |
| assert len(v) == i | |
| for j in range(i): | |
| assert v[j] == str(i - 1) | |
| def test_construct_from_list_comprehension() -> None: | |
| for i in range(50): | |
| l = [i * i for i in range(i)] | |
| v = vec[str]([str(n + 5) for n in l]) | |
| assert len(v) == i | |
| for j in range(i): | |
| assert v[j] == str(j * j + 5) | |
| def test_construct_from_list() -> None: | |
| a: list[str] = [] | |
| assert vec[str](a) == vec[str]() | |
| b = ["x", "y"] | |
| v = vec[str](b) | |
| assert len(v) == 2 | |
| assert v[0] == "x" | |
| assert v[1] == "y" | |
| for i in range(50): | |
| c = [str(j * j) for j in range(i)] | |
| v = vec[str](c) | |
| assert len(v) == i | |
| for j in range(i): | |
| assert v[j] == str(j * j) | |
| def test_construct_from_tuple() -> None: | |
| a: tuple[str, ...] = () | |
| assert vec[str](a) == vec[str]() | |
| b: tuple[str, ...] = ("x", "y") | |
| v = vec[str](b) | |
| assert len(v) == 2 | |
| assert v[0] == "x" | |
| assert v[1] == "y" | |
| def test_construct_from_iterable() -> None: | |
| for i in range(50): | |
| it: Iterable[str] = iter([str(i * i) for i in range(i)]) | |
| v = vec[str](it) | |
| assert len(v) == i | |
| for j in range(i): | |
| assert v[j] == str(j * j) | |
| def test_equality() -> None: | |
| v0 = vec[str]() | |
| v0b = vec[str]() | |
| v1 = vec[str](["1"]) | |
| v1b = vec[str](["3"]) | |
| assert v0 == v0 | |
| assert v1 == v1 | |
| assert v0 == v0b | |
| assert v0 != v1 | |
| assert v1 != v1b | |
| assert v1 != v0 | |
| def test_equality_optional() -> None: | |
| v = vec[str]() | |
| vo = vec[Optional[str]]() | |
| assert v != vo | |
| assert vo == vo | |
| vo2 = vec[Optional[str]](["x", None]) | |
| assert vo2 == vec[Optional[str]](["x", None]) | |
| assert vo2 != vec[Optional[str]](["x", "y"]) | |
| assert vo2 != vec[Optional[str]]([None, None]) | |
| assert vo2 != vec[Optional[str]](["x", None, None]) | |
| def test_str_conversion() -> None: | |
| v = vec[str]() | |
| assert str(v) == "vec[str]([])" | |
| assert repr(v) == "vec[str]([])" | |
| v = vec[str](["126"]) | |
| assert str(v) == "vec[str](['126'])" | |
| v = append(v, "5") | |
| assert str(v) == "vec[str](['126', '5'])" | |
| v = append(v, "xyz") | |
| assert str(v) == "vec[str](['126', '5', 'xyz'])" | |
| v2 = vec[Optional[str]]() | |
| assert str(v2) == "vec[str | None]([])" | |
| v2 = vec[Optional[str]](["x", None]) | |
| assert str(v2) == "vec[str | None](['x', None])" | |
| def test_for_loop() -> None: | |
| for n in vec[str](): | |
| assert False | |
| a = [] | |
| for n in vec[str](["5"]): | |
| a.append(n) | |
| assert a == ["5"] | |
| v = vec[str](["xyz", "9", "8"]) | |
| a = [] | |
| for n in v: | |
| a.append(n) | |
| assert a == ["xyz", "9", "8"] | |
| assert len(v) == 3 | |
| def test_contains() -> None: | |
| v = vec[str]() | |
| x = str() | |
| assert x not in v | |
| v = vec[str](["x"]) | |
| assert x + "x" in v | |
| assert x not in v | |
| v2 = vec[str](["xyz", "7", "9"]) | |
| assert x + "xyz" in v2 | |
| assert x + "7" in v2 | |
| assert x + "9" in v2 | |
| assert x not in v2 | |
| assert x + "x" not in v2 | |
| def test_slicing() -> None: | |
| v = vec[str]() | |
| assert v[:] == vec[str]([]) | |
| assert v[1:] == vec[str]([]) | |
| assert v[:-5] == vec[str]([]) | |
| v = vec[str](["0", "1", "2", "3", "4"]) | |
| assert v[1:4] == vec[str](["1", "2", "3"]) | |
| assert v[2:-1] == vec[str](["2", "3"]) | |
| assert v[-2:-1] == vec[str](["3"]) | |
| assert v[1:] == vec[str](["1", "2", "3", "4"]) | |
| assert v[:-1] == vec[str](["0", "1", "2", "3"]) | |
| assert v[:] == v | |
| assert v[:] is not v | |
| assert v[5:] == vec[str]() | |
| assert v[100:] == vec[str]() | |
| assert v[0:5] ==v | |
| assert v[0:5] is not v | |
| assert v[2:100] == vec[str](["2", "3", "4"]) | |
| assert v[-100:2] == vec[str](["0", "1"]) | |
| assert v[5:100] == vec[str]([]) | |
| assert v[50:100] == vec[str]([]) | |
| assert v[-100:-50] == vec[str]([]) | |
| def test_slicing_with_step() -> None: | |
| v = vec[str](["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]) | |
| assert v[1:5:2] == vec[str](["1", "3"]) | |
| assert v[1:6:2] == vec[str](["1", "3", "5"]) | |
| assert v[5:1:-2] == vec[str](["5", "3"]) | |
| assert v[6:1:-2] == vec[str](["6", "4", "2"]) | |
| v = vec[str](["0", "1", "2", "3", "4"]) | |
| assert v[::-1] == vec[str](["4", "3", "2", "1", "0"]) | |
| with assertRaises(ValueError): | |
| v[1:3:0] | |
| def test_remove() -> None: | |
| a = ["4", "7", "xyz"] | |
| for i in a: | |
| v = vec[str](a) | |
| v = remove(v, i) | |
| assert v == vec[str]([j for j in a if j != i]) | |
| v = vec[str](a) | |
| v = remove(v, "4") | |
| v = remove(v, "7") | |
| v = remove(v, "xyz") | |
| assert v == vec[str]() | |
| with assertRaises(ValueError): | |
| remove(v, "4") | |
| v = append(v, "5") | |
| with assertRaises(ValueError): | |
| remove(v, "7") | |
| v = remove(v, "5") | |
| assert len(v) == 0 | |
| v = vec[str](["1", "1", "1"]) | |
| v = remove(v, "1") | |
| assert v == vec[str](["1", "1"]) | |
| v = remove(v, "1") | |
| assert v == vec[str](["1"]) | |
| v = remove(v, "1") | |
| assert v == vec[str]() | |
| f: Any = 1.1 | |
| with assertRaises(TypeError): | |
| remove(v, f) | |
| s: Any = None | |
| with assertRaises(TypeError): | |
| remove(v, s) | |
| def test_pop_last() -> None: | |
| v = vec[str](["4", "7", "xyz"]) | |
| v, n = pop(v) | |
| assert n == "xyz" | |
| assert v == vec[str](["4", "7"]) | |
| v, n = pop(v) | |
| assert n == "7" | |
| assert v == vec[str](["4"]) | |
| v, n = pop(v) | |
| assert n == "4" | |
| assert v == vec[str]() | |
| with assertRaises(IndexError): | |
| pop(v) | |
| def test_pop_index() -> None: | |
| v = vec[str](["4", "7", "9", "15", "22"]) | |
| v, n = pop(v, 0) | |
| assert n == "4" | |
| assert v == vec[str](["7", "9", "15", "22"]) | |
| v, n = pop(v, -1) | |
| assert n == "22" | |
| assert v == vec[str](["7", "9", "15"]) | |
| v, n = pop(v, 1) | |
| assert n == "9" | |
| assert v == vec[str](["7", "15"]) | |
| with assertRaises(IndexError): | |
| pop(v, 2) | |
| with assertRaises(IndexError): | |
| pop(v, -3) | |
| v, n = pop(v, -2) | |
| assert n == "7" | |
| assert v == vec[str](["15"]) | |
| v, n = pop(v, 0) | |
| assert n == "15" | |
| assert v == vec[str]() | |
| def test_pop_optional() -> None: | |
| v = vec[Optional[str]](["x" + str(), None]) | |
| v, s = pop(v) | |
| assert s is None | |
| v, s = pop(v) | |
| assert s == "x" | |
| assert len(v) == 0 | |
| v = vec[Optional[str]](["x" + str(), None]) | |
| v, s = pop(v, 0) | |
| assert s == "x" | |
| v, s = pop(v, -1) | |
| assert s is None | |
| def test_iter_and_next() -> None: | |
| v = vec[str](["s1" + str(), "s2" + str(), "s3" + str()]) | |
| it = iter(v) | |
| assert next(it) == "s1" | |
| assert next(it) == "s2" | |
| assert next(it) == "s3" | |
| with assertRaises(StopIteration): | |
| next(it) | |
| def f(x: vec[str]) -> None: | |
| pass | |
| def test_wrapper_arg_check() -> None: | |
| f_any: Any = f | |
| with assertRaises(TypeError): | |
| f_any([]) | |
| v: Final = vec[str](["x", "y"]) | |
| def test_final() -> None: | |
| assert v == vec[str](["x", "y"]) | |
| def fdefault(v: vec[str] = vec[str](["x"])) -> vec[str]: | |
| return v | |
| def test_default_arg() -> None: | |
| assert fdefault() == vec[str](["x"]) | |
| assert fdefault(vec[str](["y"])) == vec[str](["y"]) | |
| f_any: Any = fdefault | |
| assert f_any() == vec[str](["x"]) | |
| assert f_any(vec[str](["y"])) == vec[str](["y"]) | |
| def ftuple(b: bool) -> Tuple[vec[str], vec[str]]: | |
| if b: | |
| raise RuntimeError() | |
| return vec[str](["x"]), vec[str]() | |
| def test_tuple() -> None: | |
| t = ftuple(False) | |
| assert len(t) == 2 | |
| assert t[0] == vec[str](["x"]) | |
| assert t[1] == vec[str]() | |
| a, b = t | |
| assert a == t[0] | |
| assert b == t[1] | |
| with assertRaises(RuntimeError): | |
| ftuple(True) | |
| f_any: Any = ftuple | |
| t2 = f_any(False) | |
| assert t == t2 | |
| with assertRaises(RuntimeError): | |
| f_any(True) | |
| def test_optional_item_new_syntax() -> None: | |
| v = vec[str | None]() | |
| assert len(v) == 0 | |
| assert str(v) == "vec[str | None]([])" | |
| v = append(v, 'x') | |
| v = append(v, None) | |
| assert str(v) == "vec[str | None](['x', None])" | |
| class Foo: | |
| def __init__(self, s: str) -> None: | |
| self.s = s | |
| def len_union(x: vec[str] | vec[Optional[Foo]]) -> int: | |
| return len(x) | |
| def test_union_of_vecs() -> None: | |
| assert len_union(vec[str]()) == 0 | |
| assert len_union(vec[str](["x", "y"])) == 2 | |
| assert len_union(vec[Optional[Foo]]([Foo("x"), None, Foo("y")])) == 3 | |
| with assertRaises(TypeError): | |
| a1: Any = vec[Optional[str]]() | |
| len_union(a1) | |
| with assertRaises(TypeError): | |
| a2: Any = [] | |
| len_union(a2) | |
| with assertRaises(TypeError): | |
| a3: Any = vec[bytes]() | |
| len_union(a3) | |
| with assertRaises(TypeError): | |
| a4: Any = vec[Foo]() | |
| len_union(a4) | |
| def test_append_with_alias() -> None: | |
| v = vec[str]() | |
| v = append(v, 'a') | |
| alias = v | |
| v = append(v, 'b') | |
| v = append(v, 'c') | |
| v = append(v, 'd') | |
| assert alias[0] == 'a' | |
| assert len(alias) == 1 | |
| assert v[0] == 'a' | |
| assert len(v) == 4 | |
| def test_cap_empty() -> None: | |
| v = vec[str](capacity=3) | |
| assert len(v) == 0 | |
| assert v == vec[str]() | |
| def test_cap_with_initializer() -> None: | |
| v = vec[str](['a', 'b'], capacity=3) | |
| assert len(v) == 2 | |
| assert v[0] == 'a' | |
| assert v[1] == 'b' | |
| def test_cap_from_comprehension_and_iterable() -> None: | |
| v = vec[str]([str(i) for i in range(2)], capacity=3) | |
| old = v | |
| v = append(v, '2') | |
| v[0] = 'x' | |
| assert old[0] == 'x' | |
| assert v == vec[str](['x', '1', '2']) | |
| v = vec[str]((str(i) for i in range(2)), capacity=3) | |
| old = v | |
| v = append(v, '2') | |
| v[0] = 'y' | |
| assert old[0] == 'y' | |
| assert v == vec[str](['y', '1', '2']) | |
| def test_cap_variable(n: i64 = 3) -> None: | |
| v = vec[str](capacity=n) | |
| assert len(v) == 0 | |
| v = append(v, 'x') | |
| assert v[0] == 'x' | |
| def test_cap_buffer_reuse() -> None: | |
| v = vec[str](['a', 'b'], capacity=3) | |
| old = v | |
| v = append(v, 'c') | |
| v[0] = 'z' | |
| assert old[0] == 'z' # shared buffer | |
| def test_cap_below_initializer_length() -> None: | |
| v = vec[str](['a', 'b', 'c'], capacity=1) | |
| assert len(v) == 3 | |
| assert v[0] == 'a' | |
| assert v[1] == 'b' | |
| assert v[2] == 'c' | |
| def test_cap_negative() -> None: | |
| with assertRaises(ValueError): | |
| vec[str](capacity=-1) | |
| with assertRaises(ValueError): | |
| vec[str](['x'], capacity=-1) | |
| def extend_vec(v: vec[str], v2: vec[str]) -> vec[str]: | |
| return extend(v, v2) | |
| def extend_iterable(v: vec[str], it: Iterable[str]) -> vec[str]: | |
| return extend(v, it) | |
| def test_extend_vec() -> None: | |
| v = extend_vec(vec[str](['a', 'b']), vec[str](['c', 'd'])) | |
| assert v == vec[str](['a', 'b', 'c', 'd']) | |
| def test_extend_vec_empty_src() -> None: | |
| v = extend_vec(vec[str](['a']), vec[str]()) | |
| assert v == vec[str](['a']) | |
| def test_extend_vec_empty_dst() -> None: | |
| v = extend_vec(vec[str](), vec[str](['x', 'y'])) | |
| assert v == vec[str](['x', 'y']) | |
| def test_extend_vec_fits_in_capacity() -> None: | |
| v = vec[str](['a', 'b'], capacity=3) | |
| v = extend_vec(v, vec[str](['c'])) | |
| assert v == vec[str](['a', 'b', 'c']) | |
| def test_extend_vec_exceeds_capacity() -> None: | |
| v = vec[str](['a', 'b'], capacity=3) | |
| v = extend_vec(v, vec[str](['c', 'd', 'e'])) | |
| assert v == vec[str](['a', 'b', 'c', 'd', 'e']) | |
| def test_extend_vec_multiple_doublings() -> None: | |
| v = vec[str](['x'], capacity=1) | |
| src = vec[str]() | |
| for i in range(20): | |
| src = append(src, str(i)) | |
| v = extend_vec(v, src) | |
| assert len(v) == 21 | |
| assert v[0] == 'x' | |
| assert v[20] == '19' | |
| def test_extend_vec_self() -> None: | |
| v = vec[str]() | |
| v = append(v, 'a') | |
| v = append(v, 'b') | |
| v = extend_vec(v, v) | |
| assert v == vec[str](['a', 'b', 'a', 'b']) | |
| def test_extend_vec_shared_buffer_after_pop() -> None: | |
| v0 = vec[str]() | |
| v0 = append(v0, 'a') | |
| v0 = append(v0, 'b') | |
| v0 = append(v0, 'c') | |
| v1, _ = pop(v0) | |
| # v1 and v0 share a buffer; v1.len=2, v0.len=3 | |
| v = extend_vec(v1, v0) | |
| assert v == vec[str](['a', 'b', 'a', 'b', 'c']) | |
| # src (v0) must not be corrupted | |
| assert v0 == vec[str](['a', 'b', 'c']) | |
| def test_extend_iterable_runtime_vec_shared_buffer_after_pop() -> None: | |
| v0 = vec[str]() | |
| v0 = append(v0, 'a') | |
| v0 = append(v0, 'b') | |
| v0 = append(v0, 'c') | |
| v1, _ = pop(v0) | |
| # Statically this uses VecTApi.extend, but at runtime the iterable is a vec. | |
| it: Iterable[str] = v0 | |
| v = extend_iterable(v1, it) | |
| assert v == vec[str](['a', 'b', 'a', 'b', 'c']) | |
| assert v0 == vec[str](['a', 'b', 'c']) | |
| def to_list(v: vec[str]) -> list[str]: | |
| return list(v) | |
| def to_list_optional(v: vec[Optional[str]]) -> list[Optional[str]]: | |
| return list(v) | |
| def test_to_list_empty() -> None: | |
| assert to_list(vec[str]()) == [] | |
| def test_to_list_single() -> None: | |
| assert to_list(vec[str](['hello'])) == ['hello'] | |
| def test_to_list_multiple() -> None: | |
| assert to_list(vec[str](['a', 'b', 'c'])) == ['a', 'b', 'c'] | |
| def test_to_list_optional() -> None: | |
| assert to_list_optional(vec[Optional[str]](['x', None, 'y'])) == ['x', None, 'y'] | |
| def test_to_list_does_not_consume() -> None: | |
| v = vec[str](['a', 'b']) | |
| l1 = to_list(v) | |
| l2 = to_list(v) | |
| assert l1 == l2 == ['a', 'b'] | |
| def test_to_list_shared_buffer() -> None: | |
| v0 = vec[str](['a', 'b', 'c']) | |
| v1, item = pop(v0) | |
| assert item == 'c' | |
| # v0 and v1 share a buffer (v0.len=3, v1.len=2) | |
| result = to_list(v1) | |
| assert result == ['a', 'b'] | |
| # v0 must still be valid | |
| assert v0 == vec[str](['a', 'b', 'c']) | |
| def to_tuple(v: vec[str]) -> Tuple[str, ...]: | |
| return tuple(v) | |
| def to_tuple_optional(v: vec[Optional[str]]) -> Tuple[Optional[str], ...]: | |
| return tuple(v) | |
| def test_to_tuple_empty() -> None: | |
| assert to_tuple(vec[str]()) == () | |
| def test_to_tuple_single() -> None: | |
| assert to_tuple(vec[str](['hello'])) == ('hello',) | |
| def test_to_tuple_multiple() -> None: | |
| assert to_tuple(vec[str](['a', 'b', 'c'])) == ('a', 'b', 'c') | |
| def test_to_tuple_optional() -> None: | |
| assert to_tuple_optional(vec[Optional[str]](['x', None, 'y'])) == ('x', None, 'y') | |
| def test_to_tuple_does_not_consume() -> None: | |
| v = vec[str](['a', 'b']) | |
| t1 = to_tuple(v) | |
| t2 = to_tuple(v) | |
| assert t1 == t2 == ('a', 'b') | |
| def test_to_tuple_shared_buffer() -> None: | |
| v0 = vec[str](['a', 'b', 'c']) | |
| v1, item = pop(v0) | |
| assert item == 'c' | |
| # v0 and v1 share a buffer (v0.len=3, v1.len=2) | |
| result = to_tuple(v1) | |
| assert result == ('a', 'b') | |
| # v0 must still be valid | |
| assert v0 == vec[str](['a', 'b', 'c']) |