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