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