...

Text file src/go.starlark.net/starlark/testdata/list.star

Documentation: go.starlark.net/starlark/testdata

     1# Tests of Starlark 'list'
     2
     3load("assert.star", "assert", "freeze")
     4
     5# literals
     6assert.eq([], [])
     7assert.eq([1], [1])
     8assert.eq([1], [1])
     9assert.eq([1, 2], [1, 2])
    10assert.ne([1, 2, 3], [1, 2, 4])
    11
    12# truth
    13assert.true([0])
    14assert.true(not [])
    15
    16# indexing, x[i]
    17abc = list("abc".elems())
    18assert.fails(lambda: abc[-4], "list index -4 out of range \\[-3:2]")
    19assert.eq(abc[-3], "a")
    20assert.eq(abc[-2], "b")
    21assert.eq(abc[-1], "c")
    22assert.eq(abc[0], "a")
    23assert.eq(abc[1], "b")
    24assert.eq(abc[2], "c")
    25assert.fails(lambda: abc[3], "list index 3 out of range \\[-3:2]")
    26
    27# x[i] = ...
    28x3 = [0, 1, 2]
    29x3[1] = 2
    30x3[2] += 3
    31assert.eq(x3, [0, 2, 5])
    32
    33def f2():
    34    x3[3] = 4
    35
    36assert.fails(f2, "out of range")
    37freeze(x3)
    38
    39def f3():
    40    x3[0] = 0
    41
    42assert.fails(f3, "cannot assign to element of frozen list")
    43assert.fails(x3.clear, "cannot clear frozen list")
    44
    45# list + list
    46assert.eq([1, 2, 3] + [3, 4, 5], [1, 2, 3, 3, 4, 5])
    47assert.fails(lambda: [1, 2] + (3, 4), "unknown.*list \\+ tuple")
    48assert.fails(lambda: (1, 2) + [3, 4], "unknown.*tuple \\+ list")
    49
    50# list * int,  int * list
    51assert.eq(abc * 0, [])
    52assert.eq(abc * -1, [])
    53assert.eq(abc * 1, abc)
    54assert.eq(abc * 3, ["a", "b", "c", "a", "b", "c", "a", "b", "c"])
    55assert.eq(0 * abc, [])
    56assert.eq(-1 * abc, [])
    57assert.eq(1 * abc, abc)
    58assert.eq(3 * abc, ["a", "b", "c", "a", "b", "c", "a", "b", "c"])
    59
    60# list comprehensions
    61assert.eq([2 * x for x in [1, 2, 3]], [2, 4, 6])
    62assert.eq([2 * x for x in [1, 2, 3] if x > 1], [4, 6])
    63assert.eq(
    64    [(x, y) for x in [1, 2] for y in [3, 4]],
    65    [(1, 3), (1, 4), (2, 3), (2, 4)],
    66)
    67assert.eq([(x, y) for x in [1, 2] if x == 2 for y in [3, 4]], [(2, 3), (2, 4)])
    68assert.eq([2 * x for x in (1, 2, 3)], [2, 4, 6])
    69assert.eq([x for x in "abc".elems()], ["a", "b", "c"])
    70assert.eq([x for x in {"a": 1, "b": 2}], ["a", "b"])
    71assert.eq([(y, x) for x, y in {1: 2, 3: 4}.items()], [(2, 1), (4, 3)])
    72
    73# corner cases of parsing:
    74assert.eq([x for x in range(12) if x % 2 == 0 if x % 3 == 0], [0, 6])
    75assert.eq([x for x in [1, 2] if lambda: None], [1, 2])
    76assert.eq([x for x in [1, 2] if (lambda: 3 if True else 4)], [1, 2])
    77
    78# list function
    79assert.eq(list(), [])
    80assert.eq(list("ab".elems()), ["a", "b"])
    81
    82# A list comprehension defines a separate lexical block,
    83# whether at top-level...
    84a = [1, 2]
    85b = [a for a in [3, 4]]
    86assert.eq(a, [1, 2])
    87assert.eq(b, [3, 4])
    88
    89# ...or local to a function.
    90def listcompblock():
    91    c = [1, 2]
    92    d = [c for c in [3, 4]]
    93    assert.eq(c, [1, 2])
    94    assert.eq(d, [3, 4])
    95
    96listcompblock()
    97
    98# list.pop
    99x4 = [1, 2, 3, 4, 5]
   100assert.fails(lambda: x4.pop(-6), "index -6 out of range \\[-5:4]")
   101assert.fails(lambda: x4.pop(6), "index 6 out of range \\[-5:4]")
   102assert.eq(x4.pop(), 5)
   103assert.eq(x4, [1, 2, 3, 4])
   104assert.eq(x4.pop(1), 2)
   105assert.eq(x4, [1, 3, 4])
   106assert.eq(x4.pop(0), 1)
   107assert.eq(x4, [3, 4])
   108assert.eq(x4.pop(-2), 3)
   109assert.eq(x4, [4])
   110assert.eq(x4.pop(-1), 4)
   111assert.eq(x4, [])
   112
   113# TODO(adonovan): test uses of list as sequence
   114# (for loop, comprehension, library functions).
   115
   116# x += y for lists is equivalent to x.extend(y).
   117# y may be a sequence.
   118# TODO: Test that side-effects of 'x' occur only once.
   119def list_extend():
   120    a = [1, 2, 3]
   121    b = a
   122    a = a + [4]  # creates a new list
   123    assert.eq(a, [1, 2, 3, 4])
   124    assert.eq(b, [1, 2, 3])  # b is unchanged
   125
   126    a = [1, 2, 3]
   127    b = a
   128    a += [4]  # updates a (and thus b) in place
   129    assert.eq(a, [1, 2, 3, 4])
   130    assert.eq(b, [1, 2, 3, 4])  # alias observes the change
   131
   132    a = [1, 2, 3]
   133    b = a
   134    a.extend([4])  # updates existing list
   135    assert.eq(a, [1, 2, 3, 4])
   136    assert.eq(b, [1, 2, 3, 4])  # alias observes the change
   137
   138list_extend()
   139
   140# Unlike list.extend(iterable), list += iterable makes its LHS name local.
   141a_list = []
   142
   143def f4():
   144    a_list += [1]  # binding use => a_list is a local var
   145
   146assert.fails(f4, "local variable a_list referenced before assignment")
   147
   148# list += <not iterable>
   149def f5():
   150    x = []
   151    x += 1
   152
   153assert.fails(f5, "unknown binary op: list \\+ int")
   154
   155# frozen list += iterable
   156def f6():
   157    x = []
   158    freeze(x)
   159    x += [1]
   160
   161assert.fails(f6, "cannot apply \\+= to frozen list")
   162
   163# list += hasfields (hasfields is not iterable but defines list+hasfields)
   164def f7():
   165    x = []
   166    x += hasfields()
   167    return x
   168
   169assert.eq(f7(), 42)  # weird, but exercises a corner case in list+=x.
   170
   171# append
   172x5 = [1, 2, 3]
   173x5.append(4)
   174x5.append("abc")
   175assert.eq(x5, [1, 2, 3, 4, "abc"])
   176
   177# extend
   178x5a = [1, 2, 3]
   179x5a.extend("abc".elems())  # string
   180x5a.extend((True, False))  # tuple
   181assert.eq(x5a, [1, 2, 3, "a", "b", "c", True, False])
   182
   183# list.insert
   184def insert_at(index):
   185    x = list(range(3))
   186    x.insert(index, 42)
   187    return x
   188
   189assert.eq(insert_at(-99), [42, 0, 1, 2])
   190assert.eq(insert_at(-2), [0, 42, 1, 2])
   191assert.eq(insert_at(-1), [0, 1, 42, 2])
   192assert.eq(insert_at(0), [42, 0, 1, 2])
   193assert.eq(insert_at(1), [0, 42, 1, 2])
   194assert.eq(insert_at(2), [0, 1, 42, 2])
   195assert.eq(insert_at(3), [0, 1, 2, 42])
   196assert.eq(insert_at(4), [0, 1, 2, 42])
   197
   198# list.remove
   199def remove(v):
   200    x = [3, 1, 4, 1]
   201    x.remove(v)
   202    return x
   203
   204assert.eq(remove(3), [1, 4, 1])
   205assert.eq(remove(1), [3, 4, 1])
   206assert.eq(remove(4), [3, 1, 1])
   207assert.fails(lambda: [3, 1, 4, 1].remove(42), "remove: element not found")
   208
   209# list.index
   210bananas = list("bananas".elems())
   211assert.eq(bananas.index("a"), 1)  # bAnanas
   212assert.fails(lambda: bananas.index("d"), "value not in list")
   213
   214# start
   215assert.eq(bananas.index("a", -1000), 1)  # bAnanas
   216assert.eq(bananas.index("a", 0), 1)  # bAnanas
   217assert.eq(bananas.index("a", 1), 1)  # bAnanas
   218assert.eq(bananas.index("a", 2), 3)  # banAnas
   219assert.eq(bananas.index("a", 3), 3)  # banAnas
   220assert.eq(bananas.index("b", 0), 0)  # Bananas
   221assert.eq(bananas.index("n", -3), 4)  # banaNas
   222assert.fails(lambda: bananas.index("n", -2), "value not in list")
   223assert.eq(bananas.index("s", -2), 6)  # bananaS
   224assert.fails(lambda: bananas.index("b", 1), "value not in list")
   225
   226# start, end
   227assert.eq(bananas.index("s", -1000, 7), 6)  # bananaS
   228assert.fails(lambda: bananas.index("s", -1000, 6), "value not in list")
   229assert.fails(lambda: bananas.index("d", -1000, 1000), "value not in list")
   230
   231# slicing, x[i:j:k]
   232assert.eq(bananas[6::-2], list("snnb".elems()))
   233assert.eq(bananas[5::-2], list("aaa".elems()))
   234assert.eq(bananas[4::-2], list("nnb".elems()))
   235assert.eq(bananas[99::-2], list("snnb".elems()))
   236assert.eq(bananas[100::-2], list("snnb".elems()))
   237# TODO(adonovan): many more tests
   238
   239# iterator invalidation
   240def iterator1():
   241    list = [0, 1, 2]
   242    for x in list:
   243        list[x] = 2 * x
   244    return list
   245
   246assert.fails(iterator1, "assign to element.* during iteration")
   247
   248def iterator2():
   249    list = [0, 1, 2]
   250    for x in list:
   251        list.remove(x)
   252
   253assert.fails(iterator2, "remove.*during iteration")
   254
   255def iterator3():
   256    list = [0, 1, 2]
   257    for x in list:
   258        list.append(3)
   259
   260assert.fails(iterator3, "append.*during iteration")
   261
   262def iterator4():
   263    list = [0, 1, 2]
   264    for x in list:
   265        list.extend([3, 4])
   266
   267assert.fails(iterator4, "extend.*during iteration")
   268
   269def iterator5():
   270    def f(x):
   271        x.append(4)
   272
   273    list = [1, 2, 3]
   274    _ = [f(list) for x in list]
   275
   276assert.fails(iterator5, "append.*during iteration")

View as plain text