github.com/k14s/starlark-go@v0.0.0-20200720175618-3a5c849cc368/starlark/testdata/string.star (about) 1 # Tests of Starlark 'string' 2 # option:float option:set 3 4 load("assert.star", "assert") 5 6 # raw string literals: 7 assert.eq(r'a\bc', "a\\bc") 8 9 # truth 10 assert.true("abc") 11 assert.true("\0") 12 assert.true(not "") 13 14 # str + str 15 assert.eq("a"+"b"+"c", "abc") 16 17 # str * int, int * str 18 assert.eq("abc" * 0, "") 19 assert.eq("abc" * -1, "") 20 assert.eq("abc" * 1, "abc") 21 assert.eq("abc" * 5, "abcabcabcabcabc") 22 assert.eq(0 * "abc", "") 23 assert.eq(-1 * "abc", "") 24 assert.eq(1 * "abc", "abc") 25 assert.eq(5 * "abc", "abcabcabcabcabc") 26 assert.fails(lambda: 1.0 * "abc", "unknown.*float \\* str") 27 assert.fails(lambda : "abc" * (1000000 * 1000000), "repeat count 1000000000000 too large") 28 assert.fails(lambda : "abc" * 1000000 * 1000000, "excessive repeat .3000000000000 elements") 29 30 # len 31 assert.eq(len("Hello, 世界!"), 14) 32 assert.eq(len("𐐷"), 4) # U+10437 has a 4-byte UTF-8 encoding (and a 2-code UTF-16 encoding) 33 34 # chr & ord 35 assert.eq(chr(65), "A") # 1-byte UTF-8 encoding 36 assert.eq(chr(1049), "Й") # 2-byte UTF-8 encoding 37 assert.eq(chr(0x1F63F), "😿") # 4-byte UTF-8 encoding 38 assert.fails(lambda: chr(-1), "Unicode code point -1 out of range \\(<0\\)") 39 assert.fails(lambda: chr(0x110000), "Unicode code point U\\+110000 out of range \\(>0x10FFFF\\)") 40 assert.eq(ord("A"), 65) 41 assert.eq(ord("Й"), 1049) 42 assert.eq(ord("😿"), 0x1F63F) 43 assert.eq(ord("Й"[1:]), 0xFFFD) # = Unicode replacement character 44 assert.fails(lambda: ord("abc"), "string encodes 3 Unicode code points, want 1") 45 assert.fails(lambda: ord(""), "string encodes 0 Unicode code points, want 1") 46 assert.fails(lambda: ord("😿"[1:]), "string encodes 3 Unicode code points, want 1") # 3 x 0xFFFD 47 48 # string.codepoint_ords 49 assert.eq(type("abcЙ😿".codepoint_ords()), "codepoints") 50 assert.eq(str("abcЙ😿".codepoint_ords()), '"abcЙ😿".codepoint_ords()') 51 assert.eq(list("abcЙ😿".codepoint_ords()), [97, 98, 99, 1049, 128575]) 52 assert.eq(list(("A" + "😿Z"[1:]).codepoint_ords()), [ord("A"), 0xFFFD, 0xFFFD, 0xFFFD, ord("Z")]) 53 assert.eq(list("".codepoint_ords()), []) 54 55 # string.codepoints 56 assert.eq(type("abcЙ😿".codepoints()), "codepoints") 57 assert.eq(str("abcЙ😿".codepoints()), '"abcЙ😿".codepoints()') 58 assert.eq(list("abcЙ😿".codepoints()), ["a", "b", "c", "Й", "😿"]) 59 assert.eq(list(("A" + "😿Z"[1:]).codepoints()), ["A", "\x9f", "\x98", "\xbf", "Z"]) 60 assert.eq(list("".codepoints()), []) 61 62 # string.elem_ords 63 assert.eq(type("abcЙ😿".elem_ords()), "elems") 64 assert.eq(str("abcЙ😿".elem_ords()), '"abcЙ😿".elem_ords()') 65 assert.eq(list("abcЙ😿".elem_ords()), [97, 98, 99, 208, 153, 240, 159, 152, 191]) 66 assert.eq(list(("A" + "😿Z"[1:]).elem_ords()), [65, 159, 152, 191, 90]) 67 assert.eq(list("".elem_ords()), []) 68 69 # string.elems 70 assert.eq(type("abcЙ😿".elems()), "elems") 71 assert.eq(str("abcЙ😿".elems()), '"abcЙ😿".elems()') 72 assert.eq(list("abcЙ😿".elems()), 73 ["a", "b", "c", "\xd0", "\x99", "\xf0", "\x9f", "\x98", "\xbf"]) 74 assert.eq(list(("A" + "😿Z"[1:]).elems()), 75 ["A", "\x9f", "\x98", "\xbf", "Z"]) 76 assert.eq(list("".elems()), []) 77 78 # indexing, x[i] 79 assert.eq("Hello, 世界!"[0], "H") 80 assert.eq("Hello, 世界!"[7], "\xe4") 81 assert.eq("Hello, 世界!"[13], "!") 82 assert.fails(lambda: "abc"[-4], "out of range") 83 assert.eq("abc"[-3], "a") 84 assert.eq("abc"[-2], "b") 85 assert.eq("abc"[-1], "c") 86 assert.eq("abc"[0], "a") 87 assert.eq("abc"[1], "b") 88 assert.eq("abc"[2], "c") 89 assert.fails(lambda: "abc"[4], "out of range") 90 91 # x[i] = ... 92 x2 = "abc" 93 def f(): x2[1] = 'B' 94 assert.fails(f, "string.*does not support.*assignment") 95 96 # slicing, x[i:j] 97 assert.eq("abc"[:], "abc") 98 assert.eq("abc"[-4:], "abc") 99 assert.eq("abc"[-3:], "abc") 100 assert.eq("abc"[-2:], "bc") 101 assert.eq("abc"[-1:], "c") 102 assert.eq("abc"[0:], "abc") 103 assert.eq("abc"[1:], "bc") 104 assert.eq("abc"[2:], "c") 105 assert.eq("abc"[3:], "") 106 assert.eq("abc"[4:], "") 107 assert.eq("abc"[:-4], "") 108 assert.eq("abc"[:-3], "") 109 assert.eq("abc"[:-2], "a") 110 assert.eq("abc"[:-1], "ab") 111 assert.eq("abc"[:0], "") 112 assert.eq("abc"[:1], "a") 113 assert.eq("abc"[:2], "ab") 114 assert.eq("abc"[:3], "abc") 115 assert.eq("abc"[:4], "abc") 116 assert.eq("abc"[1:2], "b") 117 assert.eq("abc"[2:1], "") 118 # non-unit strides 119 assert.eq("abcd"[0:4:1], "abcd") 120 assert.eq("abcd"[::2], "ac") 121 assert.eq("abcd"[1::2], "bd") 122 assert.eq("abcd"[4:0:-1], "dcb") 123 assert.eq("banana"[7::-2], "aaa") 124 assert.eq("banana"[6::-2], "aaa") 125 assert.eq("banana"[5::-2], "aaa") 126 assert.eq("banana"[4::-2], "nnb") 127 assert.eq("banana"[::-1], "ananab") 128 assert.eq("banana"[None:None:-2], "aaa") 129 assert.fails(lambda: "banana"[1.0::], "invalid start index: got float, want int") 130 assert.fails(lambda: "banana"[:"":], "invalid end index: got string, want int") 131 assert.fails(lambda: "banana"[:"":True], "got bool for slice step, want int") 132 133 # in, not in 134 assert.true("oo" in "food") 135 assert.true("ox" not in "food") 136 assert.true("" in "food") 137 assert.true("" in "") 138 assert.fails(lambda: 1 in "", "requires string as left operand") 139 assert.fails(lambda: "" in 1, "unknown binary op: string in int") 140 141 # ==, != 142 assert.eq("hello", "he"+"llo") 143 assert.ne("hello", "Hello") 144 145 # hash must follow java.lang.String.hashCode. 146 wanthash = { 147 "": 0, 148 "\0" * 100: 0, 149 "hello": 99162322, 150 "world": 113318802, 151 "Hello, 世界!": 417292677, 152 } 153 gothash = {s: hash(s) for s in wanthash} 154 assert.eq(gothash, wanthash) 155 156 # TODO(adonovan): ordered comparisons 157 158 # string % tuple formatting 159 assert.eq("A %d %x Z" % (123, 456), "A 123 1c8 Z") 160 assert.eq("A %(foo)d %(bar)s Z" % {"foo": 123, "bar":"hi"}, "A 123 hi Z") 161 assert.eq("%s %r" % ("hi", "hi"), 'hi "hi"') # TODO(adonovan): use ''-quotation 162 assert.eq("%%d %d" % 1, "%d 1") 163 assert.fails(lambda: "%d %d" % 1, "not enough arguments for format string") 164 assert.fails(lambda: "%d %d" % (1, 2, 3), "too many arguments for format string") 165 assert.fails(lambda: "" % 1, "too many arguments for format string") 166 # %c 167 assert.eq("%c" % 65, "A") 168 assert.eq("%c" % 0x3b1, "α") 169 assert.eq("%c" % "A", "A") 170 assert.eq("%c" % "α", "α") 171 assert.fails(lambda: "%c" % "abc", "requires a single-character string") 172 assert.fails(lambda: "%c" % "", "requires a single-character string") 173 assert.fails(lambda: "%c" % 65.0, "requires int or single-character string") 174 assert.fails(lambda: "%c" % 10000000, "requires a valid Unicode code point") 175 assert.fails(lambda: "%c" % -1, "requires a valid Unicode code point") 176 # TODO(adonovan): more tests 177 178 # str.format 179 assert.eq("a{}b".format(123), "a123b") 180 assert.eq("a{}b{}c{}d{}".format(1, 2, 3, 4), "a1b2c3d4") 181 assert.eq("a{{b".format(), "a{b") 182 assert.eq("a}}b".format(), "a}b") 183 assert.eq("a{{b}}c".format(), "a{b}c") 184 assert.eq("a{x}b{y}c{}".format(1, x=2, y=3), "a2b3c1") 185 assert.fails(lambda: "a{z}b".format(x=1), "keyword z not found") 186 assert.fails(lambda: "{-1}".format(1), "keyword -1 not found") 187 assert.fails(lambda: "{-0}".format(1), "keyword -0 not found") 188 assert.fails(lambda: "{+0}".format(1), "keyword \\+0 not found") 189 assert.fails(lambda: "{+1}".format(1), "keyword \\+1 not found") # starlark-go/issues/114 190 assert.eq("{0000000000001}".format(0, 1), "1") 191 assert.eq("{012}".format(*range(100)), "12") # decimal, despite leading zeros 192 assert.fails(lambda: '{0,1} and {1}'.format(1, 2), "keyword 0,1 not found") 193 assert.fails(lambda: "a{123}b".format(), "tuple index out of range") 194 assert.fails(lambda: "a{}b{}c".format(1), "tuple index out of range") 195 assert.eq("a{010}b".format(0,1,2,3,4,5,6,7,8,9,10), "a10b") # index is decimal 196 assert.fails(lambda: "a{}b{1}c".format(1, 2), "cannot switch from automatic field numbering to manual") 197 assert.eq("a{!s}c".format("b"), "abc") 198 assert.eq("a{!r}c".format("b"), r'a"b"c') 199 assert.eq("a{x!r}c".format(x='b'), r'a"b"c') 200 assert.fails(lambda: "{x!}".format(x=1), "unknown conversion") 201 assert.fails(lambda: "{x!:}".format(x=1), "unknown conversion") 202 assert.fails(lambda: '{a.b}'.format(1), "syntax x.y is not supported") 203 assert.fails(lambda: '{a[0]}'.format(1), "syntax a\[i\] is not supported") 204 assert.fails(lambda: '{ {} }'.format(1), "nested replacement fields not supported") 205 assert.fails(lambda: '{{}'.format(1), "single '}' in format") 206 assert.fails(lambda: '{}}'.format(1), "single '}' in format") 207 assert.fails(lambda: '}}{'.format(1), "unmatched '{' in format") 208 assert.fails(lambda: '}{{'.format(1), "single '}' in format") 209 210 # str.split, str.rsplit 211 assert.eq("a.b.c.d".split("."), ["a", "b", "c", "d"]) 212 assert.eq("a.b.c.d".rsplit("."), ["a", "b", "c", "d"]) 213 assert.eq("a.b.c.d".split(".", -1), ["a", "b", "c", "d"]) 214 assert.eq("a.b.c.d".rsplit(".", -1), ["a", "b", "c", "d"]) 215 assert.eq("a.b.c.d".split(".", 0), ["a.b.c.d"]) 216 assert.eq("a.b.c.d".rsplit(".", 0), ["a.b.c.d"]) 217 assert.eq("a.b.c.d".split(".", 1), ["a", "b.c.d"]) 218 assert.eq("a.b.c.d".rsplit(".", 1), ["a.b.c", "d"]) 219 assert.eq("a.b.c.d".split(".", 2), ["a", "b", "c.d"]) 220 assert.eq("a.b.c.d".rsplit(".", 2), ["a.b", "c", "d"]) 221 assert.eq(" ".split("."), [" "]) 222 assert.eq(" ".rsplit("."), [" "]) 223 224 # {,r}split on white space: 225 assert.eq(" a bc\n def \t ghi".split(), ["a", "bc", "def", "ghi"]) 226 assert.eq(" a bc\n def \t ghi".split(None), ["a", "bc", "def", "ghi"]) 227 assert.eq(" a bc\n def \t ghi".split(None, 0), ["a bc\n def \t ghi"]) 228 assert.eq(" a bc\n def \t ghi".rsplit(None, 0), [" a bc\n def \t ghi"]) 229 assert.eq(" a bc\n def \t ghi".split(None, 1), ["a", "bc\n def \t ghi"]) 230 assert.eq(" a bc\n def \t ghi".rsplit(None, 1), [" a bc\n def", "ghi"]) 231 assert.eq(" a bc\n def \t ghi".split(None, 2), ["a", "bc", "def \t ghi"]) 232 assert.eq(" a bc\n def \t ghi".rsplit(None, 2), [" a bc", "def", "ghi"]) 233 assert.eq(" a bc\n def \t ghi".split(None, 3), ["a", "bc", "def", "ghi"]) 234 assert.eq(" a bc\n def \t ghi".rsplit(None, 3), [" a", "bc", "def", "ghi"]) 235 assert.eq(" a bc\n def \t ghi".split(None, 4), ["a", "bc", "def", "ghi"]) 236 assert.eq(" a bc\n def \t ghi".rsplit(None, 4), ["a", "bc", "def", "ghi"]) 237 assert.eq(" a bc\n def \t ghi".rsplit(None, 5), ["a", "bc", "def", "ghi"]) 238 239 assert.eq(" a bc\n def \t ghi ".split(None, 0), ["a bc\n def \t ghi "]) 240 assert.eq(" a bc\n def \t ghi ".rsplit(None, 0), [" a bc\n def \t ghi"]) 241 assert.eq(" a bc\n def \t ghi ".split(None, 1), ["a", "bc\n def \t ghi "]) 242 assert.eq(" a bc\n def \t ghi ".rsplit(None, 1), [" a bc\n def", "ghi"]) 243 244 # Observe the algorithmic difference when splitting on spaces versus other delimiters. 245 assert.eq('--aa--bb--cc--'.split('-', 0), ['--aa--bb--cc--']) # contrast this 246 assert.eq(' aa bb cc '.split(None, 0), ['aa bb cc ']) # with this 247 assert.eq('--aa--bb--cc--'.rsplit('-', 0), ['--aa--bb--cc--']) # ditto this 248 assert.eq(' aa bb cc '.rsplit(None, 0), [' aa bb cc']) # and this 249 # 250 assert.eq('--aa--bb--cc--'.split('-', 1), ['', '-aa--bb--cc--']) 251 assert.eq('--aa--bb--cc--'.rsplit('-', 1), ['--aa--bb--cc-', '']) 252 assert.eq(' aa bb cc '.split(None, 1), ['aa', 'bb cc ']) 253 assert.eq(' aa bb cc '.rsplit(None, 1), [' aa bb', 'cc']) 254 # 255 assert.eq('--aa--bb--cc--'.split('-', -1), ['', '', 'aa', '', 'bb', '', 'cc', '', '']) 256 assert.eq('--aa--bb--cc--'.rsplit('-', -1), ['', '', 'aa', '', 'bb', '', 'cc', '', '']) 257 assert.eq(' aa bb cc '.split(None, -1), ['aa', 'bb', 'cc']) 258 assert.eq(' aa bb cc '.rsplit(None, -1), ['aa', 'bb', 'cc']) 259 assert.eq(' '.split(None), []) 260 assert.eq(' '.rsplit(None), []) 261 262 assert.eq("localhost:80".rsplit(":", 1)[-1], "80") 263 264 # str.splitlines 265 assert.eq('\nabc\ndef'.splitlines(), ['', 'abc', 'def']) 266 assert.eq('\nabc\ndef'.splitlines(True), ['\n', 'abc\n', 'def']) 267 assert.eq('\nabc\ndef\n'.splitlines(), ['', 'abc', 'def']) 268 assert.eq('\nabc\ndef\n'.splitlines(True), ['\n', 'abc\n', 'def\n']) 269 assert.eq(''.splitlines(), []) # 270 assert.eq(''.splitlines(True), []) # 271 assert.eq('a'.splitlines(), ['a']) 272 assert.eq('a'.splitlines(True), ['a']) 273 assert.eq('\n'.splitlines(), ['']) 274 assert.eq('\n'.splitlines(True), ['\n']) 275 assert.eq('a\n'.splitlines(), ['a']) 276 assert.eq('a\n'.splitlines(True), ['a\n']) 277 assert.eq('a\n\nb'.splitlines(), ['a', '', 'b']) 278 assert.eq('a\n\nb'.splitlines(True), ['a\n', '\n', 'b']) 279 assert.eq('a\nb\nc'.splitlines(), ['a', 'b', 'c']) 280 assert.eq('a\nb\nc'.splitlines(True), ['a\n', 'b\n', 'c']) 281 assert.eq('a\nb\nc\n'.splitlines(), ['a', 'b', 'c']) 282 assert.eq('a\nb\nc\n'.splitlines(True), ['a\n', 'b\n', 'c\n']) 283 284 # str.{,l,r}strip 285 assert.eq(" \tfoo\n ".strip(), "foo") 286 assert.eq(" \tfoo\n ".lstrip(), "foo\n ") 287 assert.eq(" \tfoo\n ".rstrip(), " \tfoo") 288 assert.eq(" \tfoo\n ".strip(""), "foo") 289 assert.eq(" \tfoo\n ".lstrip(""), "foo\n ") 290 assert.eq(" \tfoo\n ".rstrip(""), " \tfoo") 291 assert.eq("blah.h".strip("b.h"), "la") 292 assert.eq("blah.h".lstrip("b.h"), "lah.h") 293 assert.eq("blah.h".rstrip("b.h"), "bla") 294 295 # str.count 296 assert.eq("banana".count("a"), 3) 297 assert.eq("banana".count("a", 2), 2) 298 assert.eq("banana".count("a", -4, -2), 1) 299 assert.eq("banana".count("a", 1, 4), 2) 300 assert.eq("banana".count("a", 0, -100), 0) 301 302 # str.{starts,ends}with 303 assert.true("foo".endswith("oo")) 304 assert.true(not "foo".endswith("x")) 305 assert.true("foo".startswith("fo")) 306 assert.true(not "foo".startswith("x")) 307 assert.fails(lambda: "foo".startswith(1), "got int.*want string") 308 # 309 assert.true('abc'.startswith(('a', 'A'))) 310 assert.true('ABC'.startswith(('a', 'A'))) 311 assert.true(not 'ABC'.startswith(('b', 'B'))) 312 assert.fails(lambda: '123'.startswith((1, 2)), 'got int, for element 0') 313 assert.fails(lambda: '123'.startswith(['3']), 'got list') 314 # 315 assert.true('abc'.endswith(('c', 'C'))) 316 assert.true('ABC'.endswith(('c', 'C'))) 317 assert.true(not 'ABC'.endswith(('b', 'B'))) 318 assert.fails(lambda: '123'.endswith((1, 2)), 'got int, for element 0') 319 assert.fails(lambda: '123'.endswith(['3']), 'got list') 320 # start/end 321 assert.true('abc'.startswith('bc', 1)) 322 assert.true(not 'abc'.startswith('b', 999)) 323 assert.true('abc'.endswith('ab', None, -1)) 324 assert.true(not 'abc'.endswith('b', None, -999)) 325 326 # str.replace 327 assert.eq("banana".replace("a", "o", 1), "bonana") 328 assert.eq("banana".replace("a", "o"), "bonono") 329 # TODO(adonovan): more tests 330 331 # str.{,r}find 332 assert.eq("foofoo".find("oo"), 1) 333 assert.eq("foofoo".find("ox"), -1) 334 assert.eq("foofoo".find("oo", 2), 4) 335 assert.eq("foofoo".rfind("oo"), 4) 336 assert.eq("foofoo".rfind("ox"), -1) 337 assert.eq("foofoo".rfind("oo", 1, 4), 1) 338 assert.eq("foofoo".find(""), 0) 339 assert.eq("foofoo".rfind(""), 6) 340 341 # str.{,r}partition 342 assert.eq("foo/bar/wiz".partition("/"), ("foo", "/", "bar/wiz")) 343 assert.eq("foo/bar/wiz".rpartition("/"), ("foo/bar", "/", "wiz")) 344 assert.eq("foo/bar/wiz".partition("."), ("foo/bar/wiz", "", "")) 345 assert.eq("foo/bar/wiz".rpartition("."), ("", "", "foo/bar/wiz")) 346 assert.fails(lambda: "foo/bar/wiz".partition(""), "empty separator") 347 assert.fails(lambda: "foo/bar/wiz".rpartition(""), "empty separator") 348 349 assert.eq('?'.join(["foo", "a/b/c.go".rpartition("/")[0]]), 'foo?a/b') 350 351 # str.is{alpha,...} 352 def test_predicates(): 353 predicates = ["alnum", "alpha", "digit", "lower", "space", "title", "upper"] 354 table = { 355 "Hello, World!": "title", 356 "hello, world!": "lower", 357 "base64": "alnum lower", 358 "HAL-9000": "upper", 359 "Catch-22": "title", 360 "": "", 361 "\n\t\r": "space", 362 "abc": "alnum alpha lower", 363 "ABC": "alnum alpha upper", 364 "123": "alnum digit", 365 "DŽLJ": "alnum alpha upper", 366 "DžLj": "alnum alpha", 367 "Dž Lj": "title", 368 "džlj": "alnum alpha lower", 369 } 370 for str, want in table.items(): 371 got = ' '.join([name for name in predicates if getattr(str, "is"+name)()]) 372 if got != want: 373 assert.fail("%r matched [%s], want [%s]" % (str, got, want)) 374 test_predicates() 375 376 # Strings are not iterable. 377 # ok 378 assert.eq(len("abc"), 3) # len 379 assert.true("a" in "abc") # str in str 380 assert.eq("abc"[1], "b") # indexing 381 # not ok 382 def for_string(): 383 for x in "abc": 384 pass 385 def args(*args): return args 386 assert.fails(lambda: args(*"abc"), "must be iterable, not string") # varargs 387 assert.fails(lambda: list("abc"), "got string, want iterable") # list(str) 388 assert.fails(lambda: tuple("abc"), "got string, want iterable") # tuple(str) 389 assert.fails(lambda: set("abc"), "got string, want iterable") # set(str) 390 assert.fails(lambda: set() | "abc", "unknown binary op: set | string") # set union 391 assert.fails(lambda: enumerate("ab"), "got string, want iterable") # enumerate 392 assert.fails(lambda: sorted("abc"), "got string, want iterable") # sorted 393 assert.fails(lambda: [].extend("bc"), "got string, want iterable") # list.extend 394 assert.fails(lambda: ",".join("abc"), "got string, want iterable") # string.join 395 assert.fails(lambda: dict(["ab"]), "not iterable .*string") # dict 396 # The Java implementation does not correctly reject the following cases: 397 # (See Google Issue b/34385336) 398 assert.fails(for_string, "string value is not iterable") # for loop 399 assert.fails(lambda: [x for x in "abc"], "string value is not iterable") # comprehension 400 assert.fails(lambda: all("abc"), "got string, want iterable") # all 401 assert.fails(lambda: any("abc"), "got string, want iterable") # any 402 assert.fails(lambda: reversed("abc"), "got string, want iterable") # reversed 403 assert.fails(lambda: zip("ab", "cd"), "not iterable: string") # zip 404 405 # str.join 406 assert.eq(','.join([]), '') 407 assert.eq(','.join(["a"]), 'a') 408 assert.eq(','.join(["a", "b"]), 'a,b') 409 assert.eq(','.join(["a", "b", "c"]), 'a,b,c') 410 assert.eq(','.join(("a", "b", "c")), 'a,b,c') 411 assert.eq(''.join(("a", "b", "c")), 'abc') 412 assert.fails(lambda: ''.join(None), 'got NoneType, want iterable') 413 assert.fails(lambda: ''.join(["one", 2]), 'join: in list, want string, got int') 414 415 # TODO(adonovan): tests for: {,r}index 416 417 # str.capitalize 418 assert.eq("hElLo, WoRlD!".capitalize(), "Hello, world!") 419 assert.eq("por qué".capitalize(), "Por qué") 420 assert.eq("¿Por qué?".capitalize(), "¿por qué?") 421 422 # str.lower 423 assert.eq("hElLo, WoRlD!".lower(), "hello, world!") 424 assert.eq("por qué".lower(), "por qué") 425 assert.eq("¿Por qué?".lower(), "¿por qué?") 426 assert.eq("LJUBOVIĆ".lower(), "ljubović") 427 assert.true("dženan ljubović".islower()) 428 429 # str.upper 430 assert.eq("hElLo, WoRlD!".upper(), "HELLO, WORLD!") 431 assert.eq("por qué".upper(), "POR QUÉ") 432 assert.eq("¿Por qué?".upper(), "¿POR QUÉ?") 433 assert.eq("ljubović".upper(), "LJUBOVIĆ") 434 assert.true("DŽENAN LJUBOVIĆ".isupper()) 435 436 # str.title 437 assert.eq("hElLo, WoRlD!".title(), "Hello, World!") 438 assert.eq("por qué".title(), "Por Qué") 439 assert.eq("¿Por qué?".title(), "¿Por Qué?") 440 assert.eq("ljubović".title(), "Ljubović") 441 assert.true("Dženan Ljubović".istitle()) 442 assert.true(not "DŽenan LJubović".istitle()) 443 444 # method spell check 445 assert.fails(lambda: "".starts_with, "no .starts_with field.*did you mean .startswith") 446 assert.fails(lambda: "".StartsWith, "no .StartsWith field.*did you mean .startswith") 447 assert.fails(lambda: "".fin, "no .fin field.*.did you mean .find")