github.com/kolbycrouch/elvish@v0.14.1-0.20210614162631-215b9ac1c423/pkg/eval/builtin_fn_container_test.go (about) 1 package eval_test 2 3 import ( 4 "math" 5 "math/big" 6 "testing" 7 "unsafe" 8 9 . "src.elv.sh/pkg/eval" 10 "src.elv.sh/pkg/eval/errs" 11 12 . "src.elv.sh/pkg/eval/evaltest" 13 "src.elv.sh/pkg/eval/vals" 14 ) 15 16 func TestNsCmd(t *testing.T) { 17 Test(t, 18 That("put (ns [&name=value])[name]").Puts("value"), 19 That("n: = (ns [&name=value]); put $n:name").Puts("value"), 20 That("ns [&[]=[]]").Throws(errs.BadValue{ 21 What: `key of argument of "ns"`, 22 Valid: "string", Actual: "list"}), 23 ) 24 } 25 26 func TestMakeMap(t *testing.T) { 27 Test(t, 28 That("make-map []").Puts(vals.EmptyMap), 29 That("make-map [[k v]]").Puts(vals.MakeMap("k", "v")), 30 That("make-map [[k v] [k v2]]").Puts(vals.MakeMap("k", "v2")), 31 That("make-map [[k1 v1] [k2 v2]]"). 32 Puts(vals.MakeMap("k1", "v1", "k2", "v2")), 33 That("make-map [kv]").Puts(vals.MakeMap("k", "v")), 34 That("make-map [{ }]"). 35 Throws( 36 errs.BadValue{ 37 What: "input to make-map", Valid: "iterable", Actual: "fn"}, 38 "make-map [{ }]"), 39 That("make-map [[k]]"). 40 Throws( 41 errs.BadValue{ 42 What: "input to make-map", Valid: "iterable with 2 elements", 43 Actual: "list with 1 elements"}, 44 "make-map [[k]]"), 45 ) 46 } 47 48 var maxInt = 1<<((unsafe.Sizeof(0)*8)-1) - 1 49 var maxDenseIntInFloat = float64(1 << 53) 50 51 func TestRange(t *testing.T) { 52 Test(t, 53 That("range 3").Puts(0, 1, 2), 54 That("range 1 3").Puts(1, 2), 55 That("range 0 10 &step=3").Puts(0, 3, 6, 9), 56 // int overflow 57 That("range &step=2 "+args(vals.ToString(maxInt-3), vals.ToString(maxInt))). 58 Puts(maxInt-3, maxInt-1), 59 // non-positive int step 60 That("range &step=0 10"). 61 Throws(errs.BadValue{What: "step", Valid: "positive", Actual: "0"}), 62 63 That("range 10_000_000_000_000_000_000 10_000_000_000_000_000_003"). 64 Puts( 65 vals.ParseNum("10_000_000_000_000_000_000"), 66 vals.ParseNum("10_000_000_000_000_000_001"), 67 vals.ParseNum("10_000_000_000_000_000_002")), 68 That("range 10_000_000_000_000_000_000 10_000_000_000_000_000_003 &step=2"). 69 Puts( 70 vals.ParseNum("10_000_000_000_000_000_000"), 71 vals.ParseNum("10_000_000_000_000_000_002")), 72 // non-positive bigint step 73 That("range &step=-"+z+" 10"). 74 Throws(errs.BadValue{What: "step", Valid: "positive", Actual: "-" + z}), 75 76 That("range 23/10").Puts(0, 1, 2), 77 That("range 1/10 23/10").Puts( 78 big.NewRat(1, 10), big.NewRat(11, 10), big.NewRat(21, 10)), 79 That("range 1/10 9/10 &step=3/10").Puts( 80 big.NewRat(1, 10), big.NewRat(4, 10), big.NewRat(7, 10)), 81 // non-positive bigrat step 82 That("range &step=-1/2 10"). 83 Throws(errs.BadValue{What: "step", Valid: "positive", Actual: "-1/2"}), 84 85 That("range 1.2").Puts(0.0, 1.0), 86 That("range &step=0.5 1 3").Puts(1.0, 1.5, 2.0, 2.5), 87 // float64 overflow 88 That("range "+args(vals.ToString(maxDenseIntInFloat-2), "+inf")). 89 Puts(maxDenseIntInFloat-2, maxDenseIntInFloat-1, maxDenseIntInFloat), 90 // non-positive float64 step 91 That("range &step=-0.5 10"). 92 Throws(errs.BadValue{What: "step", Valid: "positive", Actual: "-0.5"}), 93 ) 94 } 95 96 func TestRepeat(t *testing.T) { 97 Test(t, 98 That(`repeat 4 foo`).Puts("foo", "foo", "foo", "foo"), 99 ) 100 } 101 102 func TestAssoc(t *testing.T) { 103 Test(t, 104 That(`put (assoc [0] 0 zero)[0]`).Puts("zero"), 105 That(`put (assoc [&] k v)[k]`).Puts("v"), 106 That(`put (assoc [&k=v] k v2)[k]`).Puts("v2"), 107 ) 108 } 109 110 func TestDissoc(t *testing.T) { 111 Test(t, 112 That(`has-key (dissoc [&k=v] k) k`).Puts(false), 113 ) 114 } 115 116 func TestAll(t *testing.T) { 117 Test(t, 118 That(`put foo bar | all`).Puts("foo", "bar"), 119 That(`echo foobar | all`).Puts("foobar"), 120 That(`all [foo bar]`).Puts("foo", "bar"), 121 ) 122 } 123 124 func TestOne(t *testing.T) { 125 Test(t, 126 That(`put foo | one`).Puts("foo"), 127 That(`put | one`).Throws(AnyError), 128 That(`put foo bar | one`).Throws(AnyError), 129 That(`one [foo]`).Puts("foo"), 130 That(`one []`).Throws(AnyError), 131 That(`one [foo bar]`).Throws(AnyError), 132 ) 133 } 134 135 func TestTake(t *testing.T) { 136 Test(t, 137 That(`range 100 | take 2`).Puts(0, 1), 138 ) 139 } 140 141 func TestDrop(t *testing.T) { 142 Test(t, 143 That(`range 100 | drop 98`).Puts(98, 99), 144 ) 145 } 146 147 func TestHasKey(t *testing.T) { 148 Test(t, 149 That(`has-key [foo bar] 0`).Puts(true), 150 That(`has-key [foo bar] 0:1`).Puts(true), 151 That(`has-key [foo bar] 0:20`).Puts(false), 152 That(`has-key [&lorem=ipsum &foo=bar] lorem`).Puts(true), 153 That(`has-key [&lorem=ipsum &foo=bar] loremwsq`).Puts(false), 154 ) 155 } 156 157 func TestHasValue(t *testing.T) { 158 Test(t, 159 That(`has-value [&lorem=ipsum &foo=bar] lorem`).Puts(false), 160 That(`has-value [&lorem=ipsum &foo=bar] bar`).Puts(true), 161 That(`has-value [foo bar] bar`).Puts(true), 162 That(`has-value [foo bar] badehose`).Puts(false), 163 That(`has-value "foo" o`).Puts(true), 164 That(`has-value "foo" d`).Puts(false), 165 ) 166 } 167 168 func TestCount(t *testing.T) { 169 Test(t, 170 That(`range 100 | count`).Puts(100), 171 That(`count [(range 100)]`).Puts(100), 172 That(`count 123`).Puts(3), 173 That(`count 1 2 3`).Throws( 174 errs.ArityMismatch{ 175 What: "arguments here", ValidLow: 0, ValidHigh: 1, Actual: 3}, 176 "count 1 2 3"), 177 That(`count $true`).Throws(ErrorWithMessage("cannot get length of a bool")), 178 ) 179 } 180 181 func TestKeys(t *testing.T) { 182 Test(t, 183 That(`keys [&]`).DoesNothing(), 184 That(`keys [&a=foo]`).Puts("a"), 185 // Windows does not have an external sort command. Disabled until we have a 186 // builtin sort command. 187 That(`keys [&a=foo &b=bar] | order`).Puts("a", "b"), 188 ) 189 } 190 191 func TestOrder(t *testing.T) { 192 Test(t, 193 // Ordering strings 194 That("put foo bar ipsum | order").Puts("bar", "foo", "ipsum"), 195 That("put foo bar bar | order").Puts("bar", "bar", "foo"), 196 That("put 10 1 5 2 | order").Puts("1", "10", "2", "5"), 197 198 // Ordering numbers 199 // Only small integers 200 That("put 10 1 1 | each $num~ | order").Puts(1, 1, 10), 201 That("put 10 1 5 2 -1 | each $num~ | order").Puts(-1, 1, 2, 5, 10), 202 // Small and large integers 203 That("put 1 "+z+" 2 "+z+" | each $num~ | order").Puts(1, 2, bigInt(z), bigInt(z)), 204 // Integers and rationals 205 That("put 1 2 3/2 3/2 | each $num~ | order"). 206 Puts(1, big.NewRat(3, 2), big.NewRat(3, 2), 2), 207 // Integers and floats 208 That("put 1 1.5 2 1.5 | each $num~ | order"). 209 Puts(1, 1.5, 1.5, 2), 210 // For the sake of ordering, NaN's are considered smaller than other numbers 211 That("put NaN -1 NaN | each $num~ | order").Puts(math.NaN(), math.NaN(), -1), 212 213 // Ordering lists 214 That("put [b] [a] | order").Puts(vals.MakeList("a"), vals.MakeList("b")), 215 That("put [a] [b] [a] | order"). 216 Puts(vals.MakeList("a"), vals.MakeList("a"), vals.MakeList("b")), 217 That("put [(float64 10)] [(float64 2)] | order"). 218 Puts(vals.MakeList(2.0), vals.MakeList(10.0)), 219 That("put [a b] [b b] [a c] | order"). 220 Puts( 221 vals.MakeList("a", "b"), 222 vals.MakeList("a", "c"), vals.MakeList("b", "b")), 223 That("put [a] [] [a (float64 2)] [a (float64 1)] | order"). 224 Puts(vals.EmptyList, vals.MakeList("a"), 225 vals.MakeList("a", 1.0), vals.MakeList("a", 2.0)), 226 227 // Attempting to order uncomparable values 228 That("put a (float64 1) b (float64 2) | order"). 229 Throws(ErrUncomparable, "order"), 230 That("put [a] [(float64 1)] | order"). 231 Throws(ErrUncomparable, "order"), 232 233 // &reverse 234 That("put foo bar ipsum | order &reverse").Puts("ipsum", "foo", "bar"), 235 236 // &less-than 237 That("put 1 10 2 5 | order &less-than=[a b]{ < $a $b }"). 238 Puts("1", "2", "5", "10"), 239 240 // &less-than writing more than one value 241 That("put 1 10 2 5 | order &less-than=[a b]{ put $true $false }"). 242 Throws( 243 errs.BadValue{ 244 What: "output of the &less-than callback", 245 Valid: "a single boolean", Actual: "2 values"}, 246 "order &less-than=[a b]{ put $true $false }"), 247 248 // &less-than writing non-boolean value 249 That("put 1 10 2 5 | order &less-than=[a b]{ put x }"). 250 Throws( 251 errs.BadValue{ 252 What: "output of the &less-than callback", 253 Valid: "boolean", Actual: "string"}, 254 "order &less-than=[a b]{ put x }"), 255 256 // &less-than throwing an exception 257 That("put 1 10 2 5 | order &less-than=[a b]{ fail bad }"). 258 Throws( 259 FailError{"bad"}, 260 "fail bad ", "order &less-than=[a b]{ fail bad }"), 261 262 // &less-than and &reverse 263 That("put 1 10 2 5 | order &reverse &less-than=[a b]{ < $a $b }"). 264 Puts("10", "5", "2", "1"), 265 266 // Sort should be stable - test by pretending that all values but one 267 // are equal, an check that the order among them has not changed. 268 That("put l x o x r x e x m | order &less-than=[a b]{ eq $a x }"). 269 Puts("x", "x", "x", "x", "l", "o", "r", "e", "m"), 270 ) 271 }