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