github.com/k14s/starlark-go@v0.0.0-20200720175618-3a5c849cc368/starlark/testdata/dict.star (about) 1 # Tests of Starlark 'dict' 2 # option:nesteddef 3 4 load("assert.star", "assert", "freeze") 5 6 # literals 7 assert.eq({}, {}) 8 assert.eq({"a": 1}, {"a": 1}) 9 assert.eq({"a": 1,}, {"a": 1}) 10 11 # truth 12 assert.true({False: False}) 13 assert.true(not {}) 14 15 # dict + dict is no longer supported. 16 assert.fails(lambda: {"a": 1} + {"b": 2}, 'unknown binary op: dict \+ dict') 17 18 # dict comprehension 19 assert.eq({x: x*x for x in range(3)}, {0: 0, 1: 1, 2: 4}) 20 21 # dict.pop 22 x6 = {"a": 1, "b": 2} 23 assert.eq(x6.pop("a"), 1) 24 assert.eq(str(x6), '{"b": 2}') 25 assert.fails(lambda: x6.pop("c"), "pop: missing key") 26 assert.eq(x6.pop("c", 3), 3) 27 assert.eq(x6.pop("c", None), None) # default=None tests an edge case of UnpackArgs 28 assert.eq(x6.pop("b"), 2) 29 assert.eq(len(x6), 0) 30 31 # dict.popitem 32 x7 = {"a": 1, "b": 2} 33 assert.eq([x7.popitem(), x7.popitem()], [("a", 1), ("b", 2)]) 34 assert.fails(x7.popitem, "empty dict") 35 assert.eq(len(x7), 0) 36 37 # dict.keys, dict.values 38 x8 = {"a": 1, "b": 2} 39 assert.eq(x8.keys(), ["a", "b"]) 40 assert.eq(x8.values(), [1, 2]) 41 42 # equality 43 assert.eq({"a": 1, "b": 2}, {"a": 1, "b": 2}) 44 assert.eq({"a": 1, "b": 2,}, {"a": 1, "b": 2}) 45 assert.eq({"a": 1, "b": 2}, {"b": 2, "a": 1}) 46 47 # insertion order is preserved 48 assert.eq(dict([("a", 0), ("b", 1), ("c", 2), ("b", 3)]).keys(), ["a", "b", "c"]) 49 assert.eq(dict([("b", 0), ("a", 1), ("b", 2), ("c", 3)]).keys(), ["b", "a", "c"]) 50 assert.eq(dict([("b", 0), ("a", 1), ("b", 2), ("c", 3)])["b"], 2) 51 # ...even after rehashing (which currently occurs after key 'i'): 52 small = dict([("a", 0), ("b", 1), ("c", 2)]) 53 small.update([("d", 4), ("e", 5), ("f", 6), ("g", 7), ("h", 8), ("i", 9), ("j", 10), ("k", 11)]) 54 assert.eq(small.keys(), ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]) 55 56 # Duplicate keys are not permitted in dictionary expressions (see b/35698444). 57 # (Nor in keyword args to function calls---checked by resolver.) 58 assert.fails(lambda: {"aa": 1, "bb": 2, "cc": 3, "bb": 4}, 'duplicate key: "bb"') 59 60 # Check that even with many positional args, keyword collisions are detected. 61 assert.fails(lambda: dict({'b': 3}, a=4, **dict(a=5)), 'dict: duplicate keyword arg: "a"') 62 assert.fails(lambda: dict({'a': 2, 'b': 3}, a=4, **dict(a=5)), 'dict: duplicate keyword arg: "a"') 63 # positional/keyword arg key collisions are ok 64 assert.eq(dict((['a', 2], ), a=4), {'a': 4}) 65 assert.eq(dict((['a', 2], ['a', 3]), a=4), {'a': 4}) 66 67 # index 68 def setIndex(d, k, v): 69 d[k] = v 70 71 x9 = {} 72 assert.fails(lambda: x9["a"], 'key "a" not in dict') 73 x9["a"] = 1 74 assert.eq(x9["a"], 1) 75 assert.eq(x9, {"a": 1}) 76 assert.fails(lambda: setIndex(x9, [], 2), 'unhashable type: list') 77 freeze(x9) 78 assert.fails(lambda: setIndex(x9, "a", 3), 'cannot insert into frozen hash table') 79 80 x9a = {} 81 x9a[1, 2] = 3 # unparenthesized tuple is allowed here 82 assert.eq(x9a.keys()[0], (1, 2)) 83 84 # dict.get 85 x10 = {"a": 1} 86 assert.eq(x10.get("a"), 1) 87 assert.eq(x10.get("b"), None) 88 assert.eq(x10.get("a", 2), 1) 89 assert.eq(x10.get("b", 2), 2) 90 91 # dict.clear 92 x11 = {"a": 1} 93 assert.contains(x11, "a") 94 assert.eq(x11["a"], 1) 95 x11.clear() 96 assert.fails(lambda: x11["a"], 'key "a" not in dict') 97 assert.true("a" not in x11) 98 freeze(x11) 99 assert.fails(x11.clear, "cannot clear frozen hash table") 100 101 # dict.setdefault 102 x12 = {"a": 1} 103 assert.eq(x12.setdefault("a"), 1) 104 assert.eq(x12["a"], 1) 105 assert.eq(x12.setdefault("b"), None) 106 assert.eq(x12["b"], None) 107 assert.eq(x12.setdefault("c", 2), 2) 108 assert.eq(x12["c"], 2) 109 assert.eq(x12.setdefault("c", 3), 2) 110 assert.eq(x12["c"], 2) 111 freeze(x12) 112 assert.eq(x12.setdefault("a", 1), 1) # no change, no error 113 assert.fails(lambda: x12.setdefault("d", 1), "cannot insert into frozen hash table") 114 115 # dict.update 116 x13 = {"a": 1} 117 x13.update(a=2, b=3) 118 assert.eq(x13, {"a": 2, "b": 3}) 119 x13.update([("b", 4), ("c", 5)]) 120 assert.eq(x13, {"a": 2, "b": 4, "c": 5}) 121 x13.update({"c": 6, "d": 7}) 122 assert.eq(x13, {"a": 2, "b": 4, "c": 6, "d": 7}) 123 freeze(x13) 124 assert.fails(lambda: x13.update({"a": 8}), "cannot insert into frozen hash table") 125 126 # dict as a sequence 127 # 128 # for loop 129 x14 = {1:2, 3:4} 130 def keys(dict): 131 keys = [] 132 for k in dict: keys.append(k) 133 return keys 134 assert.eq(keys(x14), [1, 3]) 135 # 136 # comprehension 137 assert.eq([x for x in x14], [1, 3]) 138 # 139 # varargs 140 def varargs(*args): return args 141 x15 = {"one": 1} 142 assert.eq(varargs(*x15), ("one",)) 143 144 # kwargs parameter does not alias the **kwargs dict 145 def kwargs(**kwargs): return kwargs 146 x16 = kwargs(**x15) 147 assert.eq(x16, x15) 148 x15["two"] = 2 # mutate 149 assert.ne(x16, x15) 150 151 # iterator invalidation 152 def iterator1(): 153 dict = {1:1, 2:1} 154 for k in dict: 155 dict[2*k] = dict[k] 156 assert.fails(iterator1, "insert.*during iteration") 157 158 def iterator2(): 159 dict = {1:1, 2:1} 160 for k in dict: 161 dict.pop(k) 162 assert.fails(iterator2, "delete.*during iteration") 163 164 def iterator3(): 165 def f(d): 166 d[3] = 3 167 dict = {1:1, 2:1} 168 _ = [f(dict) for x in dict] 169 assert.fails(iterator3, "insert.*during iteration") 170 171 # This assignment is not a modification-during-iteration: 172 # the sequence x should be completely iterated before 173 # the assignment occurs. 174 def f(): 175 x = {1:2, 2:4} 176 a, x[0] = x 177 assert.eq(a, 1) 178 assert.eq(x, {1: 2, 2: 4, 0: 2}) 179 f() 180 181 # Regression test for a bug in hashtable.delete 182 def test_delete(): 183 d = {} 184 185 # delete tail first 186 d["one"] = 1 187 d["two"] = 2 188 assert.eq(str(d), '{"one": 1, "two": 2}') 189 d.pop("two") 190 assert.eq(str(d), '{"one": 1}') 191 d.pop("one") 192 assert.eq(str(d), '{}') 193 194 # delete head first 195 d["one"] = 1 196 d["two"] = 2 197 assert.eq(str(d), '{"one": 1, "two": 2}') 198 d.pop("one") 199 assert.eq(str(d), '{"two": 2}') 200 d.pop("two") 201 assert.eq(str(d), '{}') 202 203 # delete middle 204 d["one"] = 1 205 d["two"] = 2 206 d["three"] = 3 207 assert.eq(str(d), '{"one": 1, "two": 2, "three": 3}') 208 d.pop("two") 209 assert.eq(str(d), '{"one": 1, "three": 3}') 210 d.pop("three") 211 assert.eq(str(d), '{"one": 1}') 212 d.pop("one") 213 assert.eq(str(d), '{}') 214 215 test_delete() 216 217 # Regression test for github.com/google/starlark-go/issues/128. 218 assert.fails(lambda: dict(None), 'got NoneType, want iterable') 219 assert.fails(lambda: {}.update(None), 'got NoneType, want iterable') 220 221 --- 222 # Verify position of an "unhashable key" error in a dict literal. 223 224 _ = { 225 "one": 1, 226 ["two"]: 2, ### "unhashable type: list" 227 "three": 3, 228 } 229 230 --- 231 # Verify position of a "duplicate key" error in a dict literal. 232 233 _ = { 234 "one": 1, 235 "one": 1, ### `duplicate key: "one"` 236 "three": 3, 237 } 238 239 --- 240 # Verify position of an "unhashable key" error in a dict comprehension. 241 242 _ = { 243 k: v ### "unhashable type: list" 244 for k, v in [ 245 ("one", 1), 246 (["two"], 2), 247 ("three", 3), 248 ] 249 }