builtin_fn_stream_test.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package eval_test
  2. import (
  3. "math"
  4. "math/big"
  5. "testing"
  6. . "src.elv.sh/pkg/eval"
  7. "src.elv.sh/pkg/eval/errs"
  8. . "src.elv.sh/pkg/eval/evaltest"
  9. "src.elv.sh/pkg/eval/vals"
  10. )
  11. func TestAll(t *testing.T) {
  12. Test(t,
  13. That(`put foo bar | all`).Puts("foo", "bar"),
  14. That(`echo foobar | all`).Puts("foobar"),
  15. That(`all [foo bar]`).Puts("foo", "bar"),
  16. thatOutputErrorIsBubbled("all [foo bar]"),
  17. )
  18. }
  19. func TestOne(t *testing.T) {
  20. Test(t,
  21. That(`put foo | one`).Puts("foo"),
  22. That(`put | one`).Throws(ErrorWithType(errs.ArityMismatch{})),
  23. That(`put foo bar | one`).Throws(ErrorWithType(errs.ArityMismatch{})),
  24. That(`one [foo]`).Puts("foo"),
  25. That(`one []`).Throws(ErrorWithType(errs.ArityMismatch{})),
  26. That(`one [foo bar]`).Throws(ErrorWithType(errs.ArityMismatch{})),
  27. thatOutputErrorIsBubbled("one [foo]"),
  28. )
  29. }
  30. func TestTake(t *testing.T) {
  31. Test(t,
  32. That(`range 100 | take 2`).Puts(0, 1),
  33. thatOutputErrorIsBubbled("take 1 [foo bar]"),
  34. )
  35. }
  36. func TestDrop(t *testing.T) {
  37. Test(t,
  38. That(`range 100 | drop 98`).Puts(98, 99),
  39. thatOutputErrorIsBubbled("drop 1 [foo bar lorem]"),
  40. )
  41. }
  42. func TestCompact(t *testing.T) {
  43. Test(t,
  44. That(`put a a b b c | compact`).Puts("a", "b", "c"),
  45. That(`put a b a | compact`).Puts("a", "b", "a"),
  46. thatOutputErrorIsBubbled("compact [a a]"),
  47. )
  48. }
  49. func TestCount(t *testing.T) {
  50. Test(t,
  51. That(`range 100 | count`).Puts(100),
  52. That(`count [(range 100)]`).Puts(100),
  53. That(`count 123`).Puts(3),
  54. That(`count 1 2 3`).Throws(
  55. errs.ArityMismatch{What: "arguments", ValidLow: 0, ValidHigh: 1, Actual: 3},
  56. "count 1 2 3"),
  57. That(`count $true`).Throws(ErrorWithMessage("cannot get length of a bool")),
  58. )
  59. }
  60. func TestOrder(t *testing.T) {
  61. Test(t,
  62. // Incompatible order options throws an exception.
  63. That("order &key={|v| } &less-than={|a b| }").
  64. Throws(ErrKeyAndLessThanOpts),
  65. // Ordering strings
  66. That("put foo bar ipsum | order").Puts("bar", "foo", "ipsum"),
  67. That("put foo bar bar | order").Puts("bar", "bar", "foo"),
  68. That("put 10 1 5 2 | order").Puts("1", "10", "2", "5"),
  69. // Ordering booleans
  70. That("put $true $false $true | order").Puts(false, true, true),
  71. That("put $false $true $false | order").Puts(false, false, true),
  72. // Ordering typed numbers
  73. // Only small integers
  74. That("put 10 1 1 | each $num~ | order").Puts(1, 1, 10),
  75. That("put 10 1 5 2 -1 | each $num~ | order").Puts(-1, 1, 2, 5, 10),
  76. // Small and large integers
  77. That("put 1 "+z+" 2 "+z+" | each $num~ | order").Puts(1, 2, bigInt(z), bigInt(z)),
  78. // Integers and rationals
  79. That("put 1 2 3/2 3/2 | each $num~ | order").
  80. Puts(1, big.NewRat(3, 2), big.NewRat(3, 2), 2),
  81. // Integers and floats
  82. That("put 1 1.5 2 1.5 | each $num~ | order").
  83. Puts(1, 1.5, 1.5, 2),
  84. // Mixed integers and floats.
  85. That("put (num 1) (num 1.5) (num 2) (num 1.5) | order").
  86. Puts(1, 1.5, 1.5, 2),
  87. // For the sake of ordering, NaN's are considered smaller than other numbers
  88. That("put NaN -1 NaN | each $num~ | order").Puts(math.NaN(), math.NaN(), -1),
  89. // Ordering lists
  90. That("put [b] [a] | order").Puts(vals.MakeList("a"), vals.MakeList("b")),
  91. That("put [a] [b] [a] | order").
  92. Puts(vals.MakeList("a"), vals.MakeList("a"), vals.MakeList("b")),
  93. That("put [(float64 10)] [(float64 2)] | order").
  94. Puts(vals.MakeList(2.0), vals.MakeList(10.0)),
  95. That("put [a b] [b b] [a c] | order").
  96. Puts(
  97. vals.MakeList("a", "b"),
  98. vals.MakeList("a", "c"), vals.MakeList("b", "b")),
  99. That("put [a] [] [a (num 2)] [a (num 1)] | order").
  100. Puts(vals.EmptyList, vals.MakeList("a"),
  101. vals.MakeList("a", 1), vals.MakeList("a", 2)),
  102. // Attempting to order uncomparable values
  103. That("put (num 1) 1 | order").
  104. Throws(ErrUncomparable, "order"),
  105. That("put 1 (num 1) | order").
  106. Throws(ErrUncomparable, "order"),
  107. That("put 1 (num 1) b | order").
  108. Throws(ErrUncomparable, "order"),
  109. That("put [a] a | order").
  110. Throws(ErrUncomparable, "order"),
  111. That("put [a] [(float64 1)] | order").
  112. Throws(ErrUncomparable, "order"),
  113. // &reverse
  114. That("put foo bar ipsum | order &reverse").Puts("ipsum", "foo", "bar"),
  115. // &key
  116. That("put 10 1 5 2 | order &key={|v| num $v }").
  117. Puts("1", "2", "5", "10"),
  118. That("put 10 1 5 2 | order &reverse &key={|v| num $v }").
  119. Puts("10", "5", "2", "1"),
  120. That("put 10 1 5 2 | order &key={|v| put 1 }").
  121. Puts("10", "1", "5", "2"),
  122. // &less-than
  123. That("put 1 10 2 5 | order &less-than={|a b| < $a $b }").
  124. Puts("1", "2", "5", "10"),
  125. That("put 10 1 5 2 | order &less-than=$nil").
  126. Puts("1", "10", "2", "5"),
  127. That("put 10 1 5 2 | order").
  128. Puts("1", "10", "2", "5"),
  129. // &less-than writing more than one value
  130. That("put 1 10 2 5 | order &less-than={|a b| put $true $false }").
  131. Throws(
  132. errs.BadValue{
  133. What: "output of the &less-than callback",
  134. Valid: "a single boolean", Actual: "2 values"},
  135. "order &less-than={|a b| put $true $false }"),
  136. // &less-than writing non-boolean value
  137. That("put 1 10 2 5 | order &less-than={|a b| put x }").
  138. Throws(
  139. errs.BadValue{
  140. What: "output of the &less-than callback",
  141. Valid: "boolean", Actual: "string"},
  142. "order &less-than={|a b| put x }"),
  143. // &less-than throwing an exception
  144. That("put 1 10 2 5 | order &less-than={|a b| fail bad }").
  145. Throws(
  146. FailError{"bad"},
  147. "fail bad ", "order &less-than={|a b| fail bad }"),
  148. // &less-than and &reverse
  149. That("put 1 10 2 5 | order &reverse &less-than={|a b| < $a $b }").
  150. Puts("10", "5", "2", "1"),
  151. // Sort should be stable - test by pretending that all values but one
  152. // are equal, and check that the order among them has not changed.
  153. That("put l x o x r x e x m | order &less-than={|a b| eq $a x }").
  154. Puts("x", "x", "x", "x", "l", "o", "r", "e", "m"),
  155. thatOutputErrorIsBubbled("order [foo]"),
  156. )
  157. }