github.com/kolbycrouch/elvish@v0.14.1-0.20210614162631-215b9ac1c423/pkg/eval/builtin_fn_num_test.go (about) 1 package eval_test 2 3 import ( 4 "math" 5 "math/big" 6 "strings" 7 "testing" 8 9 . "src.elv.sh/pkg/eval" 10 "src.elv.sh/pkg/eval/errs" 11 12 . "src.elv.sh/pkg/eval/evaltest" 13 ) 14 15 const ( 16 zeros = "0000000000000000000" 17 // Values that exceed the range of int64, used for testing bigint. 18 z = "1" + zeros + "0" 19 z1 = "1" + zeros + "1" // z+1 20 z2 = "1" + zeros + "2" // z+2 21 z3 = "1" + zeros + "3" // z+3 22 zz = "2" + zeros + "0" // 2z 23 zz1 = "2" + zeros + "1" // 2z+1 24 zz2 = "2" + zeros + "2" // 2z+2 25 zz3 = "2" + zeros + "3" // 2z+3 26 ) 27 28 func TestNum(t *testing.T) { 29 Test(t, 30 That("num 1").Puts(1), 31 That("num "+z).Puts(bigInt(z)), 32 That("num 1/2").Puts(big.NewRat(1, 2)), 33 That("num 0.1").Puts(0.1), 34 That("num (num 1)").Puts(1), 35 ) 36 } 37 38 func TestExactNum(t *testing.T) { 39 Test(t, 40 That("exact-num 1").Puts(1), 41 That("exact-num 0.125").Puts(big.NewRat(1, 8)), 42 That("exact-num inf").Throws(errs.BadValue{ 43 What: "argument here", Valid: "finite float", Actual: "+Inf"}), 44 ) 45 } 46 47 func TestFloat64(t *testing.T) { 48 Test(t, 49 That("float64 1").Puts(1.0), 50 That("float64 (float64 1)").Puts(1.0), 51 ) 52 } 53 54 func TestNumCmp(t *testing.T) { 55 Test(t, 56 // int 57 That("< 1 2 3").Puts(true), 58 That("< 1 3 2").Puts(false), 59 // bigint 60 That("< "+args(z1, z2, z3)).Puts(true), 61 That("< "+args(z1, z3, z2)).Puts(false), 62 // bigint and int 63 That("< "+args("1", z1)).Puts(true), 64 // bigrat 65 That("< 1/4 1/3 1/2").Puts(true), 66 That("< 1/4 1/2 1/3").Puts(false), 67 // bigrat, bigint and int 68 That("< "+args("1/2", "1", z1)).Puts(true), 69 That("< "+args("1/2", z1, "1")).Puts(false), 70 // float64 71 That("< 1.0 2.0 3.0").Puts(true), 72 That("< 1.0 3.0 2.0").Puts(false), 73 // float64, bigrat and int 74 That("< 1.0 3/2 2").Puts(true), 75 That("< 1.0 2 3/2").Puts(false), 76 77 // Mixing of types not tested for commands below; they share the same 78 // code path as <. 79 80 // int 81 That("<= 1 1 2").Puts(true), 82 That("<= 1 2 1").Puts(false), 83 // bigint 84 That("<= "+args(z1, z1, z2)).Puts(true), 85 That("<= "+args(z1, z2, z1)).Puts(false), 86 // bigrat 87 That("<= 1/3 1/3 1/2").Puts(true), 88 That("<= 1/3 1/2 1/1").Puts(true), 89 // float64 90 That("<= 1.0 1.0 2.0").Puts(true), 91 That("<= 1.0 2.0 1.0").Puts(false), 92 93 // int 94 That("== 1 1 1").Puts(true), 95 That("== 1 2 1").Puts(false), 96 // bigint 97 That("== "+args(z1, z1, z1)).Puts(true), 98 That("== "+args(z1, z2, z1)).Puts(false), 99 // bigrat 100 That("== 1/2 1/2 1/2").Puts(true), 101 That("== 1/2 1/3 1/2").Puts(false), 102 // float64 103 That("== 1.0 1.0 1.0").Puts(true), 104 That("== 1.0 2.0 1.0").Puts(false), 105 106 // int 107 That("!= 1 2 1").Puts(true), 108 That("!= 1 1 2").Puts(false), 109 // bigint 110 That("!= "+args(z1, z2, z1)).Puts(true), 111 That("!= "+args(z1, z1, z2)).Puts(false), 112 // bigrat 113 That("!= 1/2 1/3 1/2").Puts(true), 114 That("!= 1/2 1/2 1/3").Puts(false), 115 // float64 116 That("!= 1.0 2.0 1.0").Puts(true), 117 That("!= 1.0 1.0 2.0").Puts(false), 118 119 // int 120 That("> 3 2 1").Puts(true), 121 That("> 3 1 2").Puts(false), 122 // bigint 123 That("> "+args(z3, z2, z1)).Puts(true), 124 That("> "+args(z3, z1, z2)).Puts(false), 125 // bigrat 126 That("> 1/2 1/3 1/4").Puts(true), 127 That("> 1/2 1/4 1/3").Puts(false), 128 // float64 129 That("> 3.0 2.0 1.0").Puts(true), 130 That("> 3.0 1.0 2.0").Puts(false), 131 132 // int 133 That(">= 3 3 2").Puts(true), 134 That(">= 3 2 3").Puts(false), 135 // bigint 136 That(">= "+args(z3, z3, z2)).Puts(true), 137 That(">= "+args(z3, z2, z3)).Puts(false), 138 // bigrat 139 That(">= 1/2 1/2 1/3").Puts(true), 140 That(">= 1/2 1/3 1/2").Puts(false), 141 // float64 142 That(">= 3.0 3.0 2.0").Puts(true), 143 That(">= 3.0 2.0 3.0").Puts(false), 144 ) 145 } 146 147 func TestArithmeticCommands(t *testing.T) { 148 Test(t, 149 // No argument 150 That("+").Puts(0), 151 // int 152 That("+ 233100 233").Puts(233333), 153 // bigint 154 That("+ "+args(z, z1)).Puts(bigInt(zz1)), 155 // bigint and int 156 That("+ 1 2 "+z).Puts(bigInt(z3)), 157 // bigrat 158 That("+ 1/2 1/3 1/4").Puts(big.NewRat(13, 12)), 159 // bigrat, bigint and int 160 That("+ 1/2 1/2 1 "+z).Puts(bigInt(z2)), 161 // float64 162 That("+ 0.5 0.25 1.0").Puts(1.75), 163 // float64 and other types 164 That("+ 0.5 1/4 1").Puts(1.75), 165 166 // Mixing of types not tested for commands below; they share the same 167 // code path as +. 168 169 // One argument - negation 170 That("- 233").Puts(-233), 171 That("- "+z).Puts(bigInt("-"+z)), 172 That("- 1/2").Puts(big.NewRat(-1, 2)), 173 That("- 1.0").Puts(-1.0), 174 // int 175 That("- 20 10 2").Puts(8), 176 // bigint 177 That("- "+args(zz3, z1)).Puts(bigInt(z2)), 178 // float64 179 That("- 2.0 1.0 0.5").Puts(0.5), 180 181 // No argument 182 That("*").Puts(1), 183 // int 184 That("* 2 7 4").Puts(56), 185 // bigint 186 That("* 2 "+z1).Puts(bigInt(zz2)), 187 // float64 188 That("* 2.0 0.5 1.75").Puts(1.75), 189 // 0 * non-infinity 190 That("* 0 1/2 1.0").Puts(0), 191 // 0 * infinity 192 That("* 0 +Inf").Puts(math.NaN()), 193 194 // One argument - inversion 195 That("/ 2").Puts(big.NewRat(1, 2)), 196 That("/ "+z).Puts(bigRat("1/"+z)), 197 That("/ 2.0").Puts(0.5), 198 // int 199 That("/ 233333 353").Puts(661), 200 That("/ 3 4 2").Puts(big.NewRat(3, 8)), 201 // bigint 202 That("/ "+args(zz, z)).Puts(2), 203 That("/ "+args(zz, "2")).Puts(bigInt(z)), 204 That("/ "+args(z1, z)).Puts(bigRat(z1+"/"+z)), 205 // float64 206 That("/ 1.0 2.0 4.0").Puts(0.125), 207 // 0 / non-zero 208 That("/ 0 1/2 0.1").Puts(0), 209 // anything / 0 210 That("/ 0 0").Throws(ErrDivideByZero, "/ 0 0"), 211 That("/ 1 0").Throws(ErrDivideByZero, "/ 1 0"), 212 That("/ 1.0 0").Throws(ErrDivideByZero, "/ 1.0 0"), 213 214 That("% 23 7").Puts(2), 215 That("% 1 0").Throws(ErrDivideByZero, "% 1 0"), 216 ) 217 } 218 219 func TestRandint(t *testing.T) { 220 Test(t, 221 That("randint 1 2").Puts(1), 222 That("i = (randint 10 100); >= $i 10; < $i 100").Puts(true, true), 223 That("randint 2 1").Throws(ErrArgs, "randint 2 1"), 224 That("randint").Throws(ErrorWithType(errs.ArityMismatch{}), "randint"), 225 That("randint 1").Throws(ErrorWithType(errs.ArityMismatch{}), "randint 1"), 226 That("randint 1 2 3").Throws(ErrorWithType(errs.ArityMismatch{}), "randint 1 2 3"), 227 ) 228 } 229 230 func bigInt(s string) *big.Int { 231 z, ok := new(big.Int).SetString(s, 0) 232 if !ok { 233 panic("cannot parse as big int: " + s) 234 } 235 return z 236 } 237 238 func bigRat(s string) *big.Rat { 239 z, ok := new(big.Rat).SetString(s) 240 if !ok { 241 panic("cannot parse as big rat: " + s) 242 } 243 return z 244 } 245 246 func args(s ...string) string { 247 return strings.Join(s, " ") 248 }