1*4947cdc7SCole Faust# Tests of Starlark 'int' 2*4947cdc7SCole Faust 3*4947cdc7SCole Faustload("assert.star", "assert") 4*4947cdc7SCole Faust 5*4947cdc7SCole Faust# basic arithmetic 6*4947cdc7SCole Faustassert.eq(0 - 1, -1) 7*4947cdc7SCole Faustassert.eq(0 + 1, +1) 8*4947cdc7SCole Faustassert.eq(1 + 1, 2) 9*4947cdc7SCole Faustassert.eq(5 + 7, 12) 10*4947cdc7SCole Faustassert.eq(5 * 7, 35) 11*4947cdc7SCole Faustassert.eq(5 - 7, -2) 12*4947cdc7SCole Faust 13*4947cdc7SCole Faust# int boundaries 14*4947cdc7SCole Faustmaxint64 = (1 << 63) - 1 15*4947cdc7SCole Faustminint64 = -1 << 63 16*4947cdc7SCole Faustmaxint32 = (1 << 31) - 1 17*4947cdc7SCole Faustminint32 = -1 << 31 18*4947cdc7SCole Faustassert.eq(maxint64, 9223372036854775807) 19*4947cdc7SCole Faustassert.eq(minint64, -9223372036854775808) 20*4947cdc7SCole Faustassert.eq(maxint32, 2147483647) 21*4947cdc7SCole Faustassert.eq(minint32, -2147483648) 22*4947cdc7SCole Faust 23*4947cdc7SCole Faust# truth 24*4947cdc7SCole Faustdef truth(): 25*4947cdc7SCole Faust assert.true(not 0) 26*4947cdc7SCole Faust for m in [1, maxint32]: # Test small/big ranges 27*4947cdc7SCole Faust assert.true(123 * m) 28*4947cdc7SCole Faust assert.true(-1 * m) 29*4947cdc7SCole Faust 30*4947cdc7SCole Fausttruth() 31*4947cdc7SCole Faust 32*4947cdc7SCole Faust# floored division 33*4947cdc7SCole Faust# (For real division, see float.star.) 34*4947cdc7SCole Faustdef division(): 35*4947cdc7SCole Faust for m in [1, maxint32]: # Test small/big ranges 36*4947cdc7SCole Faust assert.eq((100 * m) // (7 * m), 14) 37*4947cdc7SCole Faust assert.eq((100 * m) // (-7 * m), -15) 38*4947cdc7SCole Faust assert.eq((-100 * m) // (7 * m), -15) # NB: different from Go/Java 39*4947cdc7SCole Faust assert.eq((-100 * m) // (-7 * m), 14) # NB: different from Go/Java 40*4947cdc7SCole Faust assert.eq((98 * m) // (7 * m), 14) 41*4947cdc7SCole Faust assert.eq((98 * m) // (-7 * m), -14) 42*4947cdc7SCole Faust assert.eq((-98 * m) // (7 * m), -14) 43*4947cdc7SCole Faust assert.eq((-98 * m) // (-7 * m), 14) 44*4947cdc7SCole Faust 45*4947cdc7SCole Faustdivision() 46*4947cdc7SCole Faust 47*4947cdc7SCole Faust# remainder 48*4947cdc7SCole Faustdef remainder(): 49*4947cdc7SCole Faust for m in [1, maxint32]: # Test small/big ranges 50*4947cdc7SCole Faust assert.eq((100 * m) % (7 * m), 2 * m) 51*4947cdc7SCole Faust assert.eq((100 * m) % (-7 * m), -5 * m) # NB: different from Go/Java 52*4947cdc7SCole Faust assert.eq((-100 * m) % (7 * m), 5 * m) # NB: different from Go/Java 53*4947cdc7SCole Faust assert.eq((-100 * m) % (-7 * m), -2 * m) 54*4947cdc7SCole Faust assert.eq((98 * m) % (7 * m), 0) 55*4947cdc7SCole Faust assert.eq((98 * m) % (-7 * m), 0) 56*4947cdc7SCole Faust assert.eq((-98 * m) % (7 * m), 0) 57*4947cdc7SCole Faust assert.eq((-98 * m) % (-7 * m), 0) 58*4947cdc7SCole Faust 59*4947cdc7SCole Faustremainder() 60*4947cdc7SCole Faust 61*4947cdc7SCole Faust# compound assignment 62*4947cdc7SCole Faustdef compound(): 63*4947cdc7SCole Faust x = 1 64*4947cdc7SCole Faust x += 1 65*4947cdc7SCole Faust assert.eq(x, 2) 66*4947cdc7SCole Faust x -= 3 67*4947cdc7SCole Faust assert.eq(x, -1) 68*4947cdc7SCole Faust x *= 39 69*4947cdc7SCole Faust assert.eq(x, -39) 70*4947cdc7SCole Faust x //= 4 71*4947cdc7SCole Faust assert.eq(x, -10) 72*4947cdc7SCole Faust x /= -2 73*4947cdc7SCole Faust assert.eq(x, 5) 74*4947cdc7SCole Faust x %= 3 75*4947cdc7SCole Faust assert.eq(x, 2) 76*4947cdc7SCole Faust 77*4947cdc7SCole Faust # use resolve.AllowBitwise to enable the ops: 78*4947cdc7SCole Faust x = 2 79*4947cdc7SCole Faust x &= 1 80*4947cdc7SCole Faust assert.eq(x, 0) 81*4947cdc7SCole Faust x |= 2 82*4947cdc7SCole Faust assert.eq(x, 2) 83*4947cdc7SCole Faust x ^= 3 84*4947cdc7SCole Faust assert.eq(x, 1) 85*4947cdc7SCole Faust x <<= 2 86*4947cdc7SCole Faust assert.eq(x, 4) 87*4947cdc7SCole Faust x >>= 2 88*4947cdc7SCole Faust assert.eq(x, 1) 89*4947cdc7SCole Faust 90*4947cdc7SCole Faustcompound() 91*4947cdc7SCole Faust 92*4947cdc7SCole Faust# int conversion 93*4947cdc7SCole Faust# See float.star for float-to-int conversions. 94*4947cdc7SCole Faust# We follow Python 3 here, but I can't see the method in its madness. 95*4947cdc7SCole Faust# int from bool/int/float 96*4947cdc7SCole Faustassert.fails(int, "missing argument") # int() 97*4947cdc7SCole Faustassert.eq(int(False), 0) 98*4947cdc7SCole Faustassert.eq(int(True), 1) 99*4947cdc7SCole Faustassert.eq(int(3), 3) 100*4947cdc7SCole Faustassert.eq(int(3.1), 3) 101*4947cdc7SCole Faustassert.fails(lambda: int(3, base = 10), "non-string with explicit base") 102*4947cdc7SCole Faustassert.fails(lambda: int(True, 10), "non-string with explicit base") 103*4947cdc7SCole Faust 104*4947cdc7SCole Faust# int from string, base implicitly 10 105*4947cdc7SCole Faustassert.eq(int("100000000000000000000"), 10000000000 * 10000000000) 106*4947cdc7SCole Faustassert.eq(int("-100000000000000000000"), -10000000000 * 10000000000) 107*4947cdc7SCole Faustassert.eq(int("123"), 123) 108*4947cdc7SCole Faustassert.eq(int("-123"), -123) 109*4947cdc7SCole Faustassert.eq(int("0123"), 123) # not octal 110*4947cdc7SCole Faustassert.eq(int("-0123"), -123) 111*4947cdc7SCole Faustassert.fails(lambda: int("0x12"), "invalid literal with base 10") 112*4947cdc7SCole Faustassert.fails(lambda: int("-0x12"), "invalid literal with base 10") 113*4947cdc7SCole Faustassert.fails(lambda: int("0o123"), "invalid literal.*base 10") 114*4947cdc7SCole Faustassert.fails(lambda: int("-0o123"), "invalid literal.*base 10") 115*4947cdc7SCole Faust 116*4947cdc7SCole Faust# int from string, explicit base 117*4947cdc7SCole Faustassert.eq(int("0"), 0) 118*4947cdc7SCole Faustassert.eq(int("00"), 0) 119*4947cdc7SCole Faustassert.eq(int("0", base = 10), 0) 120*4947cdc7SCole Faustassert.eq(int("00", base = 10), 0) 121*4947cdc7SCole Faustassert.eq(int("0", base = 8), 0) 122*4947cdc7SCole Faustassert.eq(int("00", base = 8), 0) 123*4947cdc7SCole Faustassert.eq(int("-0"), 0) 124*4947cdc7SCole Faustassert.eq(int("-00"), 0) 125*4947cdc7SCole Faustassert.eq(int("-0", base = 10), 0) 126*4947cdc7SCole Faustassert.eq(int("-00", base = 10), 0) 127*4947cdc7SCole Faustassert.eq(int("-0", base = 8), 0) 128*4947cdc7SCole Faustassert.eq(int("-00", base = 8), 0) 129*4947cdc7SCole Faustassert.eq(int("+0"), 0) 130*4947cdc7SCole Faustassert.eq(int("+00"), 0) 131*4947cdc7SCole Faustassert.eq(int("+0", base = 10), 0) 132*4947cdc7SCole Faustassert.eq(int("+00", base = 10), 0) 133*4947cdc7SCole Faustassert.eq(int("+0", base = 8), 0) 134*4947cdc7SCole Faustassert.eq(int("+00", base = 8), 0) 135*4947cdc7SCole Faustassert.eq(int("11", base = 9), 10) 136*4947cdc7SCole Faustassert.eq(int("-11", base = 9), -10) 137*4947cdc7SCole Faustassert.eq(int("10011", base = 2), 19) 138*4947cdc7SCole Faustassert.eq(int("-10011", base = 2), -19) 139*4947cdc7SCole Faustassert.eq(int("123", 8), 83) 140*4947cdc7SCole Faustassert.eq(int("-123", 8), -83) 141*4947cdc7SCole Faustassert.eq(int("0123", 8), 83) # redundant zeros permitted 142*4947cdc7SCole Faustassert.eq(int("-0123", 8), -83) 143*4947cdc7SCole Faustassert.eq(int("00123", 8), 83) 144*4947cdc7SCole Faustassert.eq(int("-00123", 8), -83) 145*4947cdc7SCole Faustassert.eq(int("0o123", 8), 83) 146*4947cdc7SCole Faustassert.eq(int("-0o123", 8), -83) 147*4947cdc7SCole Faustassert.eq(int("123", 7), 66) # 1*7*7 + 2*7 + 3 148*4947cdc7SCole Faustassert.eq(int("-123", 7), -66) 149*4947cdc7SCole Faustassert.eq(int("12", 16), 18) 150*4947cdc7SCole Faustassert.eq(int("-12", 16), -18) 151*4947cdc7SCole Faustassert.eq(int("0x12", 16), 18) 152*4947cdc7SCole Faustassert.eq(int("-0x12", 16), -18) 153*4947cdc7SCole Faustassert.eq(0x1000000000000001 * 0x1000000000000001, 0x1000000000000002000000000000001) 154*4947cdc7SCole Faustassert.eq(int("1010", 2), 10) 155*4947cdc7SCole Faustassert.eq(int("111111101", 2), 509) 156*4947cdc7SCole Faustassert.eq(int("0b0101", 0), 5) 157*4947cdc7SCole Faustassert.eq(int("0b0101", 2), 5) # prefix is redundant with explicit base 158*4947cdc7SCole Faustassert.eq(int("0b00000", 0), 0) 159*4947cdc7SCole Faustassert.eq(1111111111111111 * 1111111111111111, 1234567901234567654320987654321) 160*4947cdc7SCole Faustassert.fails(lambda: int("0x123", 8), "invalid literal.*base 8") 161*4947cdc7SCole Faustassert.fails(lambda: int("-0x123", 8), "invalid literal.*base 8") 162*4947cdc7SCole Faustassert.fails(lambda: int("0o123", 16), "invalid literal.*base 16") 163*4947cdc7SCole Faustassert.fails(lambda: int("-0o123", 16), "invalid literal.*base 16") 164*4947cdc7SCole Faustassert.fails(lambda: int("0x110", 2), "invalid literal.*base 2") 165*4947cdc7SCole Faust 166*4947cdc7SCole Faust# Base prefix is honored only if base=0, or if the prefix matches the explicit base. 167*4947cdc7SCole Faust# See https://github.com/google/starlark-go/issues/337 168*4947cdc7SCole Faustassert.fails(lambda: int("0b0"), "invalid literal.*base 10") 169*4947cdc7SCole Faustassert.eq(int("0b0", 0), 0) 170*4947cdc7SCole Faustassert.eq(int("0b0", 2), 0) 171*4947cdc7SCole Faustassert.eq(int("0b0", 16), 0xb0) 172*4947cdc7SCole Faustassert.eq(int("0x0b0", 16), 0xb0) 173*4947cdc7SCole Faustassert.eq(int("0x0b0", 0), 0xb0) 174*4947cdc7SCole Faustassert.eq(int("0x0b0101", 16), 0x0b0101) 175*4947cdc7SCole Faust 176*4947cdc7SCole Faust# int from string, auto detect base 177*4947cdc7SCole Faustassert.eq(int("123", 0), 123) 178*4947cdc7SCole Faustassert.eq(int("+123", 0), +123) 179*4947cdc7SCole Faustassert.eq(int("-123", 0), -123) 180*4947cdc7SCole Faustassert.eq(int("0x12", 0), 18) 181*4947cdc7SCole Faustassert.eq(int("+0x12", 0), +18) 182*4947cdc7SCole Faustassert.eq(int("-0x12", 0), -18) 183*4947cdc7SCole Faustassert.eq(int("0o123", 0), 83) 184*4947cdc7SCole Faustassert.eq(int("+0o123", 0), +83) 185*4947cdc7SCole Faustassert.eq(int("-0o123", 0), -83) 186*4947cdc7SCole Faustassert.fails(lambda: int("0123", 0), "invalid literal.*base 0") # valid in Python 2.7 187*4947cdc7SCole Faustassert.fails(lambda: int("-0123", 0), "invalid literal.*base 0") 188*4947cdc7SCole Faust 189*4947cdc7SCole Faust# github.com/google/starlark-go/issues/108 190*4947cdc7SCole Faustassert.fails(lambda: int("0Oxa", 8), "invalid literal with base 8: 0Oxa") 191*4947cdc7SCole Faust 192*4947cdc7SCole Faust# follow-on bugs to issue 108 193*4947cdc7SCole Faustassert.fails(lambda: int("--4"), "invalid literal with base 10: --4") 194*4947cdc7SCole Faustassert.fails(lambda: int("++4"), "invalid literal with base 10: \\+\\+4") 195*4947cdc7SCole Faustassert.fails(lambda: int("+-4"), "invalid literal with base 10: \\+-4") 196*4947cdc7SCole Faustassert.fails(lambda: int("0x-4", 16), "invalid literal with base 16: 0x-4") 197*4947cdc7SCole Faust 198*4947cdc7SCole Faust# bitwise union (int|int), intersection (int&int), XOR (int^int), unary not (~int), 199*4947cdc7SCole Faust# left shift (int<<int), and right shift (int>>int). 200*4947cdc7SCole Faust# use resolve.AllowBitwise to enable the ops. 201*4947cdc7SCole Faust# TODO(adonovan): this is not yet in the Starlark spec, 202*4947cdc7SCole Faust# but there is consensus that it should be. 203*4947cdc7SCole Faustassert.eq(1 | 2, 3) 204*4947cdc7SCole Faustassert.eq(3 | 6, 7) 205*4947cdc7SCole Faustassert.eq((1 | 2) & (2 | 4), 2) 206*4947cdc7SCole Faustassert.eq(1 ^ 2, 3) 207*4947cdc7SCole Faustassert.eq(2 ^ 2, 0) 208*4947cdc7SCole Faustassert.eq(1 | 0 ^ 1, 1) # check | and ^ operators precedence 209*4947cdc7SCole Faustassert.eq(~1, -2) 210*4947cdc7SCole Faustassert.eq(~(-2), 1) 211*4947cdc7SCole Faustassert.eq(~0, -1) 212*4947cdc7SCole Faustassert.eq(1 << 2, 4) 213*4947cdc7SCole Faustassert.eq(2 >> 1, 1) 214*4947cdc7SCole Faustassert.fails(lambda: 2 << -1, "negative shift count") 215*4947cdc7SCole Faustassert.fails(lambda: 1 << 512, "shift count too large") 216*4947cdc7SCole Faust 217*4947cdc7SCole Faust# comparisons 218*4947cdc7SCole Faust# TODO(adonovan): test: < > == != etc 219*4947cdc7SCole Faustdef comparisons(): 220*4947cdc7SCole Faust for m in [1, maxint32 / 2, maxint32]: # Test small/big ranges 221*4947cdc7SCole Faust assert.lt(-2 * m, -1 * m) 222*4947cdc7SCole Faust assert.lt(-1 * m, 0 * m) 223*4947cdc7SCole Faust assert.lt(0 * m, 1 * m) 224*4947cdc7SCole Faust assert.lt(1 * m, 2 * m) 225*4947cdc7SCole Faust assert.true(2 * m >= 2 * m) 226*4947cdc7SCole Faust assert.true(2 * m > 1 * m) 227*4947cdc7SCole Faust assert.true(1 * m >= 1 * m) 228*4947cdc7SCole Faust assert.true(1 * m > 0 * m) 229*4947cdc7SCole Faust assert.true(0 * m >= 0 * m) 230*4947cdc7SCole Faust assert.true(0 * m > -1 * m) 231*4947cdc7SCole Faust assert.true(-1 * m >= -1 * m) 232*4947cdc7SCole Faust assert.true(-1 * m > -2 * m) 233*4947cdc7SCole Faust 234*4947cdc7SCole Faustcomparisons() 235*4947cdc7SCole Faust 236*4947cdc7SCole Faust# precision 237*4947cdc7SCole Faustassert.eq(str(maxint64), "9223372036854775807") 238*4947cdc7SCole Faustassert.eq(str(maxint64 + 1), "9223372036854775808") 239*4947cdc7SCole Faustassert.eq(str(minint64), "-9223372036854775808") 240*4947cdc7SCole Faustassert.eq(str(minint64 - 1), "-9223372036854775809") 241*4947cdc7SCole Faustassert.eq(str(minint64 * minint64), "85070591730234615865843651857942052864") 242*4947cdc7SCole Faustassert.eq(str(maxint32 + 1), "2147483648") 243*4947cdc7SCole Faustassert.eq(str(minint32 - 1), "-2147483649") 244*4947cdc7SCole Faustassert.eq(str(minint32 * minint32), "4611686018427387904") 245*4947cdc7SCole Faustassert.eq(str(minint32 | maxint32), "-1") 246*4947cdc7SCole Faustassert.eq(str(minint32 & minint32), "-2147483648") 247*4947cdc7SCole Faustassert.eq(str(minint32 ^ maxint32), "-1") 248*4947cdc7SCole Faustassert.eq(str(minint32 // -1), "2147483648") 249*4947cdc7SCole Faust 250*4947cdc7SCole Faust# string formatting 251*4947cdc7SCole Faustassert.eq("%o %x %d" % (0o755, 0xDEADBEEF, 42), "755 deadbeef 42") 252*4947cdc7SCole Faustnums = [-95, -1, 0, +1, +95] 253*4947cdc7SCole Faustassert.eq(" ".join(["%o" % x for x in nums]), "-137 -1 0 1 137") 254*4947cdc7SCole Faustassert.eq(" ".join(["%d" % x for x in nums]), "-95 -1 0 1 95") 255*4947cdc7SCole Faustassert.eq(" ".join(["%i" % x for x in nums]), "-95 -1 0 1 95") 256*4947cdc7SCole Faustassert.eq(" ".join(["%x" % x for x in nums]), "-5f -1 0 1 5f") 257*4947cdc7SCole Faustassert.eq(" ".join(["%X" % x for x in nums]), "-5F -1 0 1 5F") 258*4947cdc7SCole Faustassert.eq("%o %x %d" % (123, 123, 123), "173 7b 123") 259*4947cdc7SCole Faustassert.eq("%o %x %d" % (123.1, 123.1, 123.1), "173 7b 123") # non-int operands are acceptable 260*4947cdc7SCole Faustassert.fails(lambda: "%d" % True, "cannot convert bool to int") 261