github.com/kolbycrouch/elvish@v0.14.1-0.20210614162631-215b9ac1c423/pkg/eval/vals/index_test.go (about)

     1  package vals
     2  
     3  import (
     4  	"testing"
     5  
     6  	"src.elv.sh/pkg/eval/errs"
     7  	. "src.elv.sh/pkg/tt"
     8  )
     9  
    10  var (
    11  	li0 = EmptyList
    12  	li4 = MakeList("foo", "bar", "lorem", "ipsum")
    13  	m   = MakeMap("foo", "bar", "lorem", "ipsum")
    14  )
    15  
    16  func TestIndex(t *testing.T) {
    17  	Test(t, Fn("Index", Index), Table{
    18  		// String indices
    19  		Args("abc", "0").Rets("a", nil),
    20  		Args("abc", 0).Rets("a", nil),
    21  		Args("你好", "0").Rets("你", nil),
    22  		Args("你好", "3").Rets("好", nil),
    23  		Args("你好", "2").Rets(Any, errIndexNotAtRuneBoundary),
    24  		// String slices with half-open range.
    25  		Args("abc", "1..2").Rets("b", nil),
    26  		Args("abc", "1..").Rets("bc", nil),
    27  		Args("abc", "..").Rets("abc", nil),
    28  		Args("abc", "..0").Rets("", nil), // i == j == 0 is allowed
    29  		Args("abc", "3..").Rets("", nil), // i == j == n is allowed
    30  		// String slices with half-open range, using deprecated syntax.
    31  		Args("abc", "1:2").Rets("b", nil),
    32  		Args("abc", "1:").Rets("bc", nil),
    33  		Args("abc", ":").Rets("abc", nil),
    34  		Args("abc", ":0").Rets("", nil), // i == j == 0 is allowed
    35  		Args("abc", "3:").Rets("", nil), // i == j == n is allowed
    36  		// String slices with closed range.
    37  		Args("abc", "0..=1").Rets("ab", nil),
    38  		Args("abc", "1..=").Rets("bc", nil),
    39  		Args("abc", "..=1").Rets("ab", nil),
    40  		Args("abc", "..=").Rets("abc", nil),
    41  
    42  		// List indices
    43  		// ============
    44  
    45  		// Simple indices: 0 <= i < n.
    46  		Args(li4, "0").Rets("foo", nil),
    47  		Args(li4, "3").Rets("ipsum", nil),
    48  		Args(li0, "0").Rets(Any, errs.OutOfRange{
    49  			What: "index here", ValidLow: "0", ValidHigh: "-1", Actual: "0"}),
    50  		Args(li4, "4").Rets(Any, errs.OutOfRange{
    51  			What: "index here", ValidLow: "0", ValidHigh: "3", Actual: "4"}),
    52  		Args(li4, "5").Rets(Any, errs.OutOfRange{
    53  			What: "index here", ValidLow: "0", ValidHigh: "3", Actual: "5"}),
    54  		// Negative indices: -n <= i < 0.
    55  		Args(li4, "-1").Rets("ipsum", nil),
    56  		Args(li4, "-4").Rets("foo", nil),
    57  		Args(li4, "-5").Rets(Any, errs.OutOfRange{
    58  			What: "negative index here", ValidLow: "-4", ValidHigh: "-1", Actual: "-5"}),
    59  		// Float indices are not allowed even if the value is an integer.
    60  		Args(li4, 0.0).Rets(Any, errIndexMustBeInteger),
    61  
    62  		// Integer indices are allowed.
    63  		Args(li4, 0).Rets("foo", nil),
    64  		Args(li4, 3).Rets("ipsum", nil),
    65  		Args(li4, 5).Rets(nil, errs.OutOfRange{
    66  			What: "index here", ValidLow: "0", ValidHigh: "3", Actual: "5"}),
    67  		Args(li4, -1).Rets("ipsum", nil),
    68  		Args(li4, -5).Rets(nil, errs.OutOfRange{
    69  			What: "negative index here", ValidLow: "-4", ValidHigh: "-1", Actual: "-5"}),
    70  
    71  		// Half-open slices.
    72  		Args(li4, "1..3").Rets(Eq(MakeList("bar", "lorem")), nil),
    73  		Args(li4, "3..4").Rets(Eq(MakeList("ipsum")), nil),
    74  		Args(li4, "0..0").Rets(Eq(EmptyList), nil), // i == j == 0 is allowed
    75  		Args(li4, "4..4").Rets(Eq(EmptyList), nil), // i == j == n is allowed
    76  		// i defaults to 0
    77  		Args(li4, "..2").Rets(Eq(MakeList("foo", "bar")), nil),
    78  		Args(li4, "..-1").Rets(Eq(MakeList("foo", "bar", "lorem")), nil),
    79  		// j defaults to n
    80  		Args(li4, "3..").Rets(Eq(MakeList("ipsum")), nil),
    81  		Args(li4, "-2..").Rets(Eq(MakeList("lorem", "ipsum")), nil),
    82  		// Both indices can be omitted.
    83  		Args(li0, "..").Rets(Eq(li0), nil),
    84  		Args(li4, "..").Rets(Eq(li4), nil),
    85  
    86  		// Half-open slices using deprecated syntax.
    87  		Args(li4, "1:3").Rets(Eq(MakeList("bar", "lorem")), nil),
    88  		Args(li4, "3:4").Rets(Eq(MakeList("ipsum")), nil),
    89  		Args(li4, "0:0").Rets(Eq(EmptyList), nil), // i == j == 0 is allowed
    90  		Args(li4, "4:4").Rets(Eq(EmptyList), nil), // i == j == n is allowed
    91  		Args(li4, ":2").Rets(Eq(MakeList("foo", "bar")), nil),
    92  		Args(li4, ":-1").Rets(Eq(MakeList("foo", "bar", "lorem")), nil),
    93  		Args(li4, "3:").Rets(Eq(MakeList("ipsum")), nil),
    94  		Args(li4, "-2:").Rets(Eq(MakeList("lorem", "ipsum")), nil),
    95  		Args(li0, ":").Rets(Eq(li0), nil),
    96  		Args(li4, ":").Rets(Eq(li4), nil),
    97  
    98  		// Closed slices.
    99  		Args(li4, "1..=2").Rets(Eq(MakeList("bar", "lorem")), nil),
   100  		Args(li4, "..=1").Rets(Eq(MakeList("foo", "bar")), nil),
   101  		Args(li4, "..=-2").Rets(Eq(MakeList("foo", "bar", "lorem")), nil),
   102  		Args(li4, "3..=").Rets(Eq(MakeList("ipsum")), nil),
   103  		Args(li4, "..=").Rets(Eq(li4), nil),
   104  
   105  		// Index out of range.
   106  		Args(li4, "-5:1").Rets(nil, errs.OutOfRange{
   107  			What: "negative index here", ValidLow: "-4", ValidHigh: "-1", Actual: "-5"}),
   108  		Args(li4, "0:5").Rets(nil, errs.OutOfRange{
   109  			What: "index here", ValidLow: "0", ValidHigh: "4", Actual: "5"}),
   110  		Args(li4, "3:2").Rets(nil, errs.OutOfRange{
   111  			What: "slice upper index here", ValidLow: "3", ValidHigh: "4", Actual: "2"}),
   112  
   113  		// Malformed list indices.
   114  		Args(li4, "a").Rets(Any, errIndexMustBeInteger),
   115  		// TODO(xiaq): Make the error more accurate.
   116  		Args(li4, "1:3:2").Rets(Any, errIndexMustBeInteger),
   117  
   118  		// Map indices
   119  		// ============
   120  
   121  		Args(m, "foo").Rets("bar", nil),
   122  		Args(m, "bad").Rets(Any, NoSuchKey("bad")),
   123  	})
   124  }