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  }