github.com/elves/elvish@v0.15.0/pkg/eval/vals/index_test.go (about)

     1  package vals
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/elves/elvish/pkg/eval/errs"
     7  	. "github.com/elves/elvish/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.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  		// Decimal indices are not allowed even if the value is an integer.
    60  		Args(li4, "0.0").Rets(Any, errIndexMustBeInteger),
    61  
    62  		// Float64 indices are allowed as long as they are integers.
    63  		Args(li4, 0.0).Rets("foo", nil),
    64  		Args(li4, 3.0).Rets("ipsum", nil),
    65  		Args(li4, 5.0).Rets(nil, errs.OutOfRange{
    66  			What: "index here", ValidLow: "0", ValidHigh: "3", Actual: "5"}),
    67  		Args(li4, -1.0).Rets("ipsum", nil),
    68  		Args(li4, -5.0).Rets(nil, errs.OutOfRange{
    69  			What: "negative index here", ValidLow: "-4", ValidHigh: "-1", Actual: "-5"}),
    70  		Args(li4, 0.5).Rets(Any, errIndexMustBeInteger),
    71  
    72  		// Half-open slices.
    73  		Args(li4, "1..3").Rets(Eq(MakeList("bar", "lorem")), nil),
    74  		Args(li4, "3..4").Rets(Eq(MakeList("ipsum")), nil),
    75  		Args(li4, "0..0").Rets(Eq(EmptyList), nil), // i == j == 0 is allowed
    76  		Args(li4, "4..4").Rets(Eq(EmptyList), nil), // i == j == n is allowed
    77  		// i defaults to 0
    78  		Args(li4, "..2").Rets(Eq(MakeList("foo", "bar")), nil),
    79  		Args(li4, "..-1").Rets(Eq(MakeList("foo", "bar", "lorem")), nil),
    80  		// j defaults to n
    81  		Args(li4, "3..").Rets(Eq(MakeList("ipsum")), nil),
    82  		Args(li4, "-2..").Rets(Eq(MakeList("lorem", "ipsum")), nil),
    83  		// Both indices can be omitted.
    84  		Args(li0, "..").Rets(Eq(li0), nil),
    85  		Args(li4, "..").Rets(Eq(li4), nil),
    86  
    87  		// Half-open slices using deprecated syntax.
    88  		Args(li4, "1:3").Rets(Eq(MakeList("bar", "lorem")), nil),
    89  		Args(li4, "3:4").Rets(Eq(MakeList("ipsum")), nil),
    90  		Args(li4, "0:0").Rets(Eq(EmptyList), nil), // i == j == 0 is allowed
    91  		Args(li4, "4:4").Rets(Eq(EmptyList), nil), // i == j == n is allowed
    92  		Args(li4, ":2").Rets(Eq(MakeList("foo", "bar")), nil),
    93  		Args(li4, ":-1").Rets(Eq(MakeList("foo", "bar", "lorem")), nil),
    94  		Args(li4, "3:").Rets(Eq(MakeList("ipsum")), nil),
    95  		Args(li4, "-2:").Rets(Eq(MakeList("lorem", "ipsum")), nil),
    96  		Args(li0, ":").Rets(Eq(li0), nil),
    97  		Args(li4, ":").Rets(Eq(li4), nil),
    98  
    99  		// Closed slices.
   100  		Args(li4, "1..=2").Rets(Eq(MakeList("bar", "lorem")), nil),
   101  		Args(li4, "..=1").Rets(Eq(MakeList("foo", "bar")), nil),
   102  		Args(li4, "..=-2").Rets(Eq(MakeList("foo", "bar", "lorem")), nil),
   103  		Args(li4, "3..=").Rets(Eq(MakeList("ipsum")), nil),
   104  		Args(li4, "..=").Rets(Eq(li4), nil),
   105  
   106  		// Index out of range.
   107  		Args(li4, "-5:1").Rets(nil, errs.OutOfRange{
   108  			What: "negative index here", ValidLow: "-4", ValidHigh: "-1", Actual: "-5"}),
   109  		Args(li4, "0:5").Rets(nil, errs.OutOfRange{
   110  			What: "index here", ValidLow: "0", ValidHigh: "4", Actual: "5"}),
   111  		Args(li4, "3:2").Rets(nil, errs.OutOfRange{
   112  			What: "slice upper index here", ValidLow: "3", ValidHigh: "4", Actual: "2"}),
   113  
   114  		// Malformed list indices.
   115  		Args(li4, "a").Rets(Any, errIndexMustBeInteger),
   116  		// TODO(xiaq): Make the error more accurate.
   117  		Args(li4, "1:3:2").Rets(Any, errIndexMustBeInteger),
   118  
   119  		// Map indices
   120  		// ============
   121  
   122  		Args(m, "foo").Rets("bar", nil),
   123  		Args(m, "bad").Rets(Any, NoSuchKey("bad")),
   124  	})
   125  }
   126  
   127  func TestCheckDeprecatedIndex(t *testing.T) {
   128  	Test(t, Fn("CheckDeprecatedIndex", CheckDeprecatedIndex), Table{
   129  		Args("ab", "1:2").Rets("using : for slice is deprecated; use .. instead"),
   130  		Args("ab", "1").Rets(""),
   131  		Args("ab", "1..2").Rets(""),
   132  		Args("ab", 1.0).Rets(""),
   133  		Args(li4, "1:2").Rets("using : for slice is deprecated; use .. instead"),
   134  		Args(li4, "1").Rets(""),
   135  		Args(li4, "1..2").Rets(""),
   136  		Args(li4, 1.0).Rets(""),
   137  	})
   138  }