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