github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/runtime/list_test.go (about)

     1  // Copyright 2016 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package grumpy
    16  
    17  import (
    18  	"math/big"
    19  	"reflect"
    20  	"testing"
    21  )
    22  
    23  func TestNewList(t *testing.T) {
    24  	cases := [][]*Object{
    25  		nil,
    26  		[]*Object{newObject(ObjectType)},
    27  		[]*Object{newObject(ObjectType), newObject(ObjectType)},
    28  	}
    29  	for _, args := range cases {
    30  		l := NewList(args...)
    31  		if !reflect.DeepEqual(l.elems, args) {
    32  			t.Errorf("NewList(%v) = %v, want %v", args, l.elems, args)
    33  		}
    34  	}
    35  }
    36  
    37  func TestListBinaryOps(t *testing.T) {
    38  	cases := []struct {
    39  		fun     func(f *Frame, v, w *Object) (*Object, *BaseException)
    40  		v, w    *Object
    41  		want    *Object
    42  		wantExc *BaseException
    43  	}{
    44  		{Add, newTestList(3).ToObject(), newTestList("foo").ToObject(), newTestList(3, "foo").ToObject(), nil},
    45  		{Add, NewList(None).ToObject(), NewList().ToObject(), NewList(None).ToObject(), nil},
    46  		{Add, NewList().ToObject(), newObject(ObjectType), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for +: 'list' and 'object'")},
    47  		{Add, None, NewList().ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for +: 'NoneType' and 'list'")},
    48  		{Mul, NewList().ToObject(), NewInt(10).ToObject(), NewList().ToObject(), nil},
    49  		{Mul, newTestList("baz").ToObject(), NewInt(-2).ToObject(), NewList().ToObject(), nil},
    50  		{Mul, NewList(None, None).ToObject(), NewInt(0).ToObject(), NewList().ToObject(), nil},
    51  		{Mul, newTestList(1, "bar").ToObject(), NewInt(2).ToObject(), newTestList(1, "bar", 1, "bar").ToObject(), nil},
    52  		{Mul, NewInt(1).ToObject(), newTestList(1, "bar").ToObject(), newTestList(1, "bar").ToObject(), nil},
    53  		{Mul, newObject(ObjectType), NewList(newObject(ObjectType)).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for *: 'object' and 'list'")},
    54  		{Mul, NewList(newObject(ObjectType)).ToObject(), NewList().ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for *: 'list' and 'list'")},
    55  		{Mul, NewList(None, None).ToObject(), NewInt(MaxInt).ToObject(), nil, mustCreateException(OverflowErrorType, "result too large")},
    56  	}
    57  	for _, cas := range cases {
    58  		testCase := invokeTestCase{args: wrapArgs(cas.v, cas.w), want: cas.want, wantExc: cas.wantExc}
    59  		if err := runInvokeTestCase(wrapFuncForTest(cas.fun), &testCase); err != "" {
    60  			t.Error(err)
    61  		}
    62  	}
    63  }
    64  
    65  func TestListCompare(t *testing.T) {
    66  	o := newObject(ObjectType)
    67  	cases := []invokeTestCase{
    68  		{args: wrapArgs(NewList(), NewList()), want: compareAllResultEq},
    69  		{args: wrapArgs(newTestList("foo", o), newTestList("foo", o)), want: compareAllResultEq},
    70  		{args: wrapArgs(newTestList(4), newTestList(3, 0)), want: compareAllResultGT},
    71  		{args: wrapArgs(newTestList(4), newTestList(4, 3, 0)), want: compareAllResultLT},
    72  		{args: wrapArgs(NewList(o), NewList()), want: compareAllResultGT},
    73  		{args: wrapArgs(NewList(o), newTestList("foo")), want: compareAllResultLT},
    74  	}
    75  	for _, cas := range cases {
    76  		if err := runInvokeTestCase(compareAll, &cas); err != "" {
    77  			t.Error(err)
    78  		}
    79  	}
    80  }
    81  
    82  func TestListCount(t *testing.T) {
    83  	cases := []invokeTestCase{
    84  		{args: wrapArgs(NewList(), NewInt(1)), want: NewInt(0).ToObject()},
    85  		{args: wrapArgs(NewList(None, None, None), None), want: NewInt(3).ToObject()},
    86  		{args: wrapArgs(newTestList()), wantExc: mustCreateException(TypeErrorType, "'count' of 'list' requires 2 arguments")},
    87  	}
    88  	for _, cas := range cases {
    89  		if err := runInvokeMethodTestCase(ListType, "count", &cas); err != "" {
    90  			t.Error(err)
    91  		}
    92  	}
    93  }
    94  
    95  func TestListDelItem(t *testing.T) {
    96  	badIndexType := newTestClass("badIndex", []*Type{ObjectType}, newStringDict(map[string]*Object{
    97  		"__index__": newBuiltinFunction("__index__", func(f *Frame, _ Args, _ KWArgs) (*Object, *BaseException) {
    98  			return nil, f.RaiseType(ValueErrorType, "wut")
    99  		}).ToObject(),
   100  	}))
   101  	delItem := mustNotRaise(GetAttr(NewRootFrame(), ListType.ToObject(), NewStr("__delitem__"), nil))
   102  	fun := wrapFuncForTest(func(f *Frame, l *List, key *Object) (*Object, *BaseException) {
   103  		_, raised := delItem.Call(f, wrapArgs(l, key), nil)
   104  		if raised != nil {
   105  			return nil, raised
   106  		}
   107  		return l.ToObject(), nil
   108  	})
   109  	cases := []invokeTestCase{
   110  		{args: wrapArgs(newTestRange(3), 0), want: newTestList(1, 2).ToObject()},
   111  		{args: wrapArgs(newTestRange(3), 2), want: newTestList(0, 1).ToObject()},
   112  		{args: wrapArgs(NewList(), 101), wantExc: mustCreateException(IndexErrorType, "index out of range")},
   113  		{args: wrapArgs(NewList(), newTestSlice(50, 100)), want: NewList().ToObject()},
   114  		{args: wrapArgs(newTestList(1, 2, 3, 4, 5), newTestSlice(1, 3, None)), want: newTestList(1, 4, 5).ToObject()},
   115  		{args: wrapArgs(newTestList(1, 2, 3, 4, 5), newTestSlice(1, None, 2)), want: newTestList(1, 3, 5).ToObject()},
   116  		{args: wrapArgs(newTestList(1, 2, 3, 4, 5), newTestSlice(big.NewInt(1), None, 2)), want: newTestList(1, 3, 5).ToObject()},
   117  		{args: wrapArgs(newTestList(1, 2, 3, 4, 5), newTestSlice(1, big.NewInt(5), 2)), want: newTestList(1, 3, 5).ToObject()},
   118  		{args: wrapArgs(newTestList(1, 2, 3, 4, 5), newTestSlice(1, None, big.NewInt(2))), want: newTestList(1, 3, 5).ToObject()},
   119  		{args: wrapArgs(newTestList(1, 2, 3, 4, 5), newTestSlice(1.0, 3, None)), wantExc: mustCreateException(TypeErrorType, errBadSliceIndex)},
   120  		{args: wrapArgs(newTestList(1, 2, 3, 4, 5), newTestSlice(None, None, 4)), want: newTestList(2, 3, 4).ToObject()},
   121  		{args: wrapArgs(newTestRange(10), newTestSlice(1, 8, 3)), want: newTestList(0, 2, 3, 5, 6, 8, 9).ToObject()},
   122  		{args: wrapArgs(newTestList(1, 2, 3), newTestSlice(1, None, 0)), wantExc: mustCreateException(ValueErrorType, "slice step cannot be zero")},
   123  		{args: wrapArgs(newTestList(true), None), wantExc: mustCreateException(TypeErrorType, "list indices must be integers, not NoneType")},
   124  		{args: wrapArgs(newTestList(true), newObject(badIndexType)), wantExc: mustCreateException(ValueErrorType, "wut")},
   125  	}
   126  	for _, cas := range cases {
   127  		if err := runInvokeTestCase(fun, &cas); err != "" {
   128  			t.Error(err)
   129  		}
   130  	}
   131  }
   132  
   133  func TestListIndex(t *testing.T) {
   134  	intIndexType := newTestClass("IntIndex", []*Type{ObjectType}, newStringDict(map[string]*Object{
   135  		"__index__": newBuiltinFunction("__index__", func(f *Frame, _ Args, _ KWArgs) (*Object, *BaseException) {
   136  			return NewInt(0).ToObject(), nil
   137  		}).ToObject(),
   138  	}))
   139  	cases := []invokeTestCase{
   140  		{args: wrapArgs(newTestList(), 1, "foo"), wantExc: mustCreateException(TypeErrorType, "slice indices must be integers or None or have an __index__ method")},
   141  		{args: wrapArgs(newTestList(10, 20, 30), 20), want: NewInt(1).ToObject()},
   142  		{args: wrapArgs(newTestList(10, 20, 30), 20, newObject(intIndexType)), want: NewInt(1).ToObject()},
   143  		{args: wrapArgs(newTestList(0, "foo", "bar"), "foo"), want: NewInt(1).ToObject()},
   144  		{args: wrapArgs(newTestList(0, 1, 2, 3, 4), 3, 3), want: NewInt(3).ToObject()},
   145  		{args: wrapArgs(newTestList(0, 2.0, 2, 3, 4, 2, 1, "foo"), 3, 3), want: NewInt(3).ToObject()},
   146  		{args: wrapArgs(newTestList(0, 1, 2, 3, 4), 3, 4), wantExc: mustCreateException(ValueErrorType, "3 is not in list")},
   147  		{args: wrapArgs(newTestList(0, 1, 2, 3, 4), 3, 0, 4), want: NewInt(3).ToObject()},
   148  		{args: wrapArgs(newTestList(0, 1, 2, 3, 4), 3, 0, 3), wantExc: mustCreateException(ValueErrorType, "3 is not in list")},
   149  		{args: wrapArgs(newTestList(0, 1, 2, 3, 4), 3, -2), want: NewInt(3).ToObject()},
   150  		{args: wrapArgs(newTestList(0, 1, 2, 3, 4), 3, -1), wantExc: mustCreateException(ValueErrorType, "3 is not in list")},
   151  		{args: wrapArgs(newTestList(0, 1, 2, 3, 4), 3, 0, -1), want: NewInt(3).ToObject()},
   152  		{args: wrapArgs(newTestList(0, 1, 2, 3, 4), 3, 0, -2), wantExc: mustCreateException(ValueErrorType, "3 is not in list")},
   153  		{args: wrapArgs(newTestList(0, 1, 2, 3, 4), 3, 0, 999), want: NewInt(3).ToObject()},
   154  		{args: wrapArgs(newTestList(0, 1, 2, 3, 4), "foo", 0, 999), wantExc: mustCreateException(ValueErrorType, "'foo' is not in list")},
   155  		{args: wrapArgs(newTestList(0, 1, 2, 3, 4), 3, 999), wantExc: mustCreateException(ValueErrorType, "3 is not in list")},
   156  		{args: wrapArgs(newTestList(0, 1, 2, 3, 4), 3, 5, 0), wantExc: mustCreateException(ValueErrorType, "3 is not in list")},
   157  	}
   158  	for _, cas := range cases {
   159  		if err := runInvokeMethodTestCase(ListType, "index", &cas); err != "" {
   160  			t.Error(err)
   161  		}
   162  	}
   163  }
   164  
   165  func TestListRemove(t *testing.T) {
   166  	fun := newBuiltinFunction("TestListRemove", func(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   167  		rem, raised := GetAttr(f, ListType.ToObject(), NewStr("remove"), nil)
   168  		if raised != nil {
   169  			return nil, raised
   170  		}
   171  		if _, raised := rem.Call(f, args, nil); raised != nil {
   172  			return nil, raised
   173  		}
   174  		return args[0], nil
   175  	}).ToObject()
   176  	cases := []invokeTestCase{
   177  		{args: wrapArgs(newTestList(1, 2, 3), 2), want: newTestList(1, 3).ToObject()},
   178  		{args: wrapArgs(newTestList(1, 2, 3, 2, 1), 2), want: newTestList(1, 3, 2, 1).ToObject()},
   179  		{args: wrapArgs(NewList()), wantExc: mustCreateException(TypeErrorType, "'remove' of 'list' requires 2 arguments")},
   180  		{args: wrapArgs(NewList(), 1), wantExc: mustCreateException(ValueErrorType, "list.remove(x): x not in list")},
   181  	}
   182  	for _, cas := range cases {
   183  		if err := runInvokeTestCase(fun, &cas); err != "" {
   184  			t.Error(err)
   185  		}
   186  	}
   187  }
   188  
   189  func BenchmarkListContains(b *testing.B) {
   190  	b.Run("false-3", func(b *testing.B) {
   191  		t := newTestList("foo", 42, "bar").ToObject()
   192  		a := wrapArgs(1)[0]
   193  		f := NewRootFrame()
   194  		b.ResetTimer()
   195  		for i := 0; i < b.N; i++ {
   196  			Contains(f, t, a)
   197  		}
   198  	})
   199  
   200  	b.Run("false-10", func(b *testing.B) {
   201  		t := newTestList("foo", 42, "bar", "foo", 42, "bar", "foo", 42, "bar", "baz").ToObject()
   202  		a := wrapArgs(1)[0]
   203  		f := NewRootFrame()
   204  		b.ResetTimer()
   205  		for i := 0; i < b.N; i++ {
   206  			Contains(f, t, a)
   207  		}
   208  	})
   209  
   210  	b.Run("true-3.1", func(b *testing.B) {
   211  		t := newTestList("foo", 42, "bar").ToObject()
   212  		a := wrapArgs("foo")[0]
   213  		f := NewRootFrame()
   214  		b.ResetTimer()
   215  		for i := 0; i < b.N; i++ {
   216  			Contains(f, t, a)
   217  		}
   218  	})
   219  
   220  	b.Run("true-3.3", func(b *testing.B) {
   221  		t := newTestList("foo", 42, "bar").ToObject()
   222  		a := wrapArgs("bar")[0]
   223  		f := NewRootFrame()
   224  		b.ResetTimer()
   225  		for i := 0; i < b.N; i++ {
   226  			Contains(f, t, a)
   227  		}
   228  	})
   229  
   230  	b.Run("true-10.10", func(b *testing.B) {
   231  		t := newTestList("foo", 42, "bar", "foo", 42, "bar", "foo", 42, "bar", "baz").ToObject()
   232  		a := wrapArgs("baz")[0]
   233  		f := NewRootFrame()
   234  		b.ResetTimer()
   235  		for i := 0; i < b.N; i++ {
   236  			Contains(f, t, a)
   237  		}
   238  	})
   239  }
   240  
   241  func TestListGetItem(t *testing.T) {
   242  	cases := []invokeTestCase{
   243  		{args: wrapArgs(newTestRange(20), 0), want: NewInt(0).ToObject()},
   244  		{args: wrapArgs(newTestRange(20), 19), want: NewInt(19).ToObject()},
   245  		{args: wrapArgs(NewList(), 101), wantExc: mustCreateException(IndexErrorType, "index out of range")},
   246  		{args: wrapArgs(NewList(), newTestSlice(50, 100)), want: NewList().ToObject()},
   247  		{args: wrapArgs(newTestList(1, 2, 3, 4, 5), newTestSlice(1, 3, None)), want: newTestList(2, 3).ToObject()},
   248  		{args: wrapArgs(newTestList(1, 2, 3, 4, 5), newTestSlice(1, None, 2)), want: newTestList(2, 4).ToObject()},
   249  		{args: wrapArgs(newTestList(1, 2, 3, 4, 5), newTestSlice(big.NewInt(1), None, 2)), want: newTestList(2, 4).ToObject()},
   250  		{args: wrapArgs(newTestList(1, 2, 3, 4, 5), newTestSlice(1, big.NewInt(5), 2)), want: newTestList(2, 4).ToObject()},
   251  		{args: wrapArgs(newTestList(1, 2, 3, 4, 5), newTestSlice(1, None, big.NewInt(2))), want: newTestList(2, 4).ToObject()},
   252  		{args: wrapArgs(newTestList(1, 2, 3, 4, 5), newTestSlice(1.0, 3, None)), wantExc: mustCreateException(TypeErrorType, errBadSliceIndex)},
   253  		{args: wrapArgs(newTestList(1, 2, 3), newTestSlice(1, None, 0)), wantExc: mustCreateException(ValueErrorType, "slice step cannot be zero")},
   254  		{args: wrapArgs(newTestList(true), None), wantExc: mustCreateException(TypeErrorType, "list indices must be integers, not NoneType")},
   255  	}
   256  	for _, cas := range cases {
   257  		if err := runInvokeMethodTestCase(ListType, "__getitem__", &cas); err != "" {
   258  			t.Error(err)
   259  		}
   260  	}
   261  }
   262  
   263  func TestListInplaceOps(t *testing.T) {
   264  	cases := []struct {
   265  		fun     func(f *Frame, v, w *Object) (*Object, *BaseException)
   266  		v, w    *Object
   267  		want    *Object
   268  		wantExc *BaseException
   269  	}{
   270  		{IAdd, newTestList(3).ToObject(), newTestList("foo").ToObject(), newTestList(3, "foo").ToObject(), nil},
   271  		{IAdd, NewList(None).ToObject(), NewList().ToObject(), NewList(None).ToObject(), nil},
   272  		{IAdd, NewList().ToObject(), newObject(ObjectType), nil, mustCreateException(TypeErrorType, "'object' object is not iterable")},
   273  		{IMul, NewList().ToObject(), NewInt(10).ToObject(), NewList().ToObject(), nil},
   274  		{IMul, newTestList("baz").ToObject(), NewInt(-2).ToObject(), NewList().ToObject(), nil},
   275  		{IMul, NewList().ToObject(), None, nil, mustCreateException(TypeErrorType, "can't multiply sequence by non-int of type 'NoneType'")},
   276  	}
   277  	for _, cas := range cases {
   278  		switch got, result := checkInvokeResult(wrapFuncForTest(cas.fun), []*Object{cas.v, cas.w}, cas.want, cas.wantExc); result {
   279  		case checkInvokeResultExceptionMismatch:
   280  			t.Errorf("%s(%v, %v) raised %v, want %v", getFuncName(cas.fun), cas.v, cas.w, got, cas.wantExc)
   281  		case checkInvokeResultReturnValueMismatch:
   282  			t.Errorf("%s(%v, %v) = %v, want %v", getFuncName(cas.fun), cas.v, cas.w, got, cas.want)
   283  		default:
   284  			if got != nil && got != cas.v {
   285  				t.Errorf("%s(%v, %v) did not return identity", getFuncName(cas.fun), cas.v, cas.w)
   286  			}
   287  		}
   288  	}
   289  }
   290  
   291  func TestListIsTrue(t *testing.T) {
   292  	cases := []invokeTestCase{
   293  		{args: wrapArgs(NewList()), want: False.ToObject()},
   294  		{args: wrapArgs(newTestList("foo", None)), want: True.ToObject()},
   295  	}
   296  	for _, cas := range cases {
   297  		if err := runInvokeTestCase(wrapFuncForTest(IsTrue), &cas); err != "" {
   298  			t.Error(err)
   299  		}
   300  	}
   301  }
   302  
   303  func TestListAppend(t *testing.T) {
   304  	fun := newBuiltinFunction("TestListAppend", func(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   305  		if raised := checkFunctionArgs(f, "TestListAppend", args, ListType, ObjectType); raised != nil {
   306  			return nil, raised
   307  		}
   308  		app, raised := GetAttr(f, ListType.ToObject(), NewStr("append"), nil)
   309  		if raised != nil {
   310  			return nil, raised
   311  		}
   312  		if _, raised := app.Call(f, args, nil); raised != nil {
   313  			return nil, raised
   314  		}
   315  		return args[0], nil
   316  	}).ToObject()
   317  	cases := []invokeTestCase{
   318  		{args: wrapArgs(NewList(), None), want: NewList(None).ToObject()},
   319  		{args: wrapArgs(NewList(None), 42), want: newTestList(None, 42).ToObject()},
   320  		{args: wrapArgs(newTestList(None, 42), "foo"), want: newTestList(None, 42, "foo").ToObject()},
   321  		{args: wrapArgs(newTestRange(100), 100), want: newTestRange(101).ToObject()},
   322  	}
   323  	for _, cas := range cases {
   324  		if err := runInvokeTestCase(fun, &cas); err != "" {
   325  			t.Error(err)
   326  		}
   327  	}
   328  }
   329  
   330  func TestListExtend(t *testing.T) {
   331  	extend := mustNotRaise(GetAttr(NewRootFrame(), ListType.ToObject(), NewStr("extend"), nil))
   332  	fun := newBuiltinFunction("TestListExtend", func(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   333  		if _, raised := extend.Call(f, args, nil); raised != nil {
   334  			return nil, raised
   335  		}
   336  		return args[0], nil
   337  	}).ToObject()
   338  	cases := []invokeTestCase{
   339  		{args: wrapArgs(newTestList(), newTestTuple()), want: newTestList().ToObject()},
   340  		{args: wrapArgs(newTestList(), newTestList()), want: newTestList().ToObject()},
   341  		{args: wrapArgs(newTestList(3), newTestList("foo")), want: newTestList(3, "foo").ToObject()},
   342  		{args: wrapArgs(newTestList(), newTestList("foo")), want: newTestList("foo").ToObject()},
   343  		{args: wrapArgs(newTestList(3), newTestList()), want: newTestList(3).ToObject()},
   344  		{args: wrapArgs(NewStr(""), newTestList()), wantExc: mustCreateException(TypeErrorType, "unbound method extend() must be called with list instance as first argument (got str instance instead)")},
   345  		{args: wrapArgs(None, None), wantExc: mustCreateException(TypeErrorType, "unbound method extend() must be called with list instance as first argument (got NoneType instance instead)")},
   346  		{args: wrapArgs(newTestList(3), None), wantExc: mustCreateException(TypeErrorType, "'NoneType' object is not iterable")},
   347  		{args: wrapArgs(newTestRange(5), newTestList(3)), want: newTestList(0, 1, 2, 3, 4, 3).ToObject()},
   348  		{args: wrapArgs(newTestRange(5), newTestList(3)), want: newTestList(0, 1, 2, 3, 4, 3).ToObject()},
   349  		{args: wrapArgs(newTestTuple(1, 2, 3), newTestList(3)), wantExc: mustCreateException(TypeErrorType, "unbound method extend() must be called with list instance as first argument (got tuple instance instead)")},
   350  		{args: wrapArgs(newTestList(4), newTestTuple(1, 2, 3)), want: newTestList(4, 1, 2, 3).ToObject()},
   351  		{args: wrapArgs(newTestList()), wantExc: mustCreateException(TypeErrorType, "extend() takes exactly one argument (1 given)")},
   352  		{args: wrapArgs(newTestList(), newTestTuple(), newTestTuple()), wantExc: mustCreateException(TypeErrorType, "extend() takes exactly one argument (3 given)")},
   353  	}
   354  	for _, cas := range cases {
   355  		if err := runInvokeTestCase(fun, &cas); err != "" {
   356  			t.Error(err)
   357  		}
   358  	}
   359  }
   360  
   361  func TestListLen(t *testing.T) {
   362  	cases := []invokeTestCase{
   363  		{args: wrapArgs(NewList()), want: NewInt(0).ToObject()},
   364  		{args: wrapArgs(NewList(None, None, None)), want: NewInt(3).ToObject()},
   365  	}
   366  	for _, cas := range cases {
   367  		if err := runInvokeMethodTestCase(ListType, "__len__", &cas); err != "" {
   368  			t.Error(err)
   369  		}
   370  	}
   371  }
   372  
   373  func TestListNew(t *testing.T) {
   374  	cases := []invokeTestCase{
   375  		{want: NewList().ToObject()},
   376  		{args: wrapArgs(newTestTuple(1, 2, 3)), want: newTestList(1, 2, 3).ToObject()},
   377  		{args: wrapArgs(newTestDict(1, "foo", "bar", None)), want: newTestList(1, "bar").ToObject()},
   378  		{args: wrapArgs(42), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")},
   379  	}
   380  	for _, cas := range cases {
   381  		if err := runInvokeTestCase(ListType.ToObject(), &cas); err != "" {
   382  			t.Error(err)
   383  		}
   384  	}
   385  }
   386  
   387  func TestListReverse(t *testing.T) {
   388  	reverse := mustNotRaise(GetAttr(NewRootFrame(), ListType.ToObject(), NewStr("reverse"), nil))
   389  	fun := wrapFuncForTest(func(f *Frame, o *Object, args ...*Object) (*Object, *BaseException) {
   390  		_, raised := reverse.Call(f, append(Args{o}, args...), nil)
   391  		if raised != nil {
   392  			return nil, raised
   393  		}
   394  		return o, nil
   395  	})
   396  	cases := []invokeTestCase{
   397  		{args: wrapArgs(NewList()), want: NewList().ToObject()},
   398  		{args: wrapArgs(newTestList(1, 2, 3)), want: newTestList(3, 2, 1).ToObject()},
   399  		{args: wrapArgs(NewList(), 123), wantExc: mustCreateException(TypeErrorType, "'reverse' of 'list' requires 1 arguments")},
   400  	}
   401  	for _, cas := range cases {
   402  		if err := runInvokeTestCase(fun, &cas); err != "" {
   403  			t.Error(err)
   404  		}
   405  	}
   406  }
   407  
   408  func TestListStrRepr(t *testing.T) {
   409  	recursiveList := newTestList("foo").ToObject()
   410  	listAppend(NewRootFrame(), []*Object{recursiveList, recursiveList}, nil)
   411  	cases := []invokeTestCase{
   412  		{args: wrapArgs(NewList()), want: NewStr("[]").ToObject()},
   413  		{args: wrapArgs(newTestList("foo")), want: NewStr("['foo']").ToObject()},
   414  		{args: wrapArgs(newTestList(TupleType, ExceptionType)), want: NewStr("[<type 'tuple'>, <type 'Exception'>]").ToObject()},
   415  		{args: wrapArgs(recursiveList), want: NewStr("['foo', [...]]").ToObject()},
   416  	}
   417  	for _, cas := range cases {
   418  		if err := runInvokeTestCase(wrapFuncForTest(ToStr), &cas); err != "" {
   419  			t.Error(err)
   420  		}
   421  		if err := runInvokeTestCase(wrapFuncForTest(Repr), &cas); err != "" {
   422  			t.Error(err)
   423  		}
   424  	}
   425  }
   426  
   427  func TestListInsert(t *testing.T) {
   428  	fun := wrapFuncForTest(func(f *Frame, l *List, args ...*Object) (*Object, *BaseException) {
   429  		insert, raised := GetAttr(NewRootFrame(), l.ToObject(), NewStr("insert"), nil)
   430  		if raised != nil {
   431  			return nil, raised
   432  		}
   433  		if _, raised := insert.Call(f, args, nil); raised != nil {
   434  			return nil, raised
   435  		}
   436  		return l.ToObject(), nil
   437  	})
   438  	cases := []invokeTestCase{
   439  		{args: wrapArgs(NewList(), 0, None), want: NewList(None).ToObject()},
   440  		{args: wrapArgs(newTestList("bar"), -100, "foo"), want: newTestList("foo", "bar").ToObject()},
   441  		{args: wrapArgs(newTestList("foo", "bar"), 101, "baz"), want: newTestList("foo", "bar", "baz").ToObject()},
   442  		{args: wrapArgs(newTestList("a", "c"), 1, "b"), want: newTestList("a", "b", "c").ToObject()},
   443  		{args: wrapArgs(newTestList(1, 2), 0, 0), want: newTestList(0, 1, 2).ToObject()},
   444  		{args: wrapArgs(NewList()), wantExc: mustCreateException(TypeErrorType, "'insert' of 'list' requires 3 arguments")},
   445  		{args: wrapArgs(NewList(), "foo", 123), wantExc: mustCreateException(TypeErrorType, "'insert' requires a 'int' object but received a 'str'")},
   446  	}
   447  	for _, cas := range cases {
   448  		if err := runInvokeTestCase(fun, &cas); err != "" {
   449  			t.Error(err)
   450  		}
   451  	}
   452  }
   453  
   454  func TestListIter(t *testing.T) {
   455  	fun := newBuiltinFunction("TestListIter", func(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   456  		if raised := checkFunctionArgs(f, "TestListIter", args, ListType); raised != nil {
   457  			return nil, raised
   458  		}
   459  		var got []*Object
   460  		iter, raised := Iter(f, args[0])
   461  		if raised != nil {
   462  			return nil, raised
   463  		}
   464  		raised = seqApply(f, iter, func(elems []*Object, _ bool) *BaseException {
   465  			got = make([]*Object, len(elems))
   466  			copy(got, elems)
   467  			return nil
   468  		})
   469  		if raised != nil {
   470  			return nil, raised
   471  		}
   472  		return NewList(got...).ToObject(), nil
   473  	}).ToObject()
   474  	o := newObject(ObjectType)
   475  	cases := []invokeTestCase{
   476  		{args: wrapArgs(NewList()), want: NewList().ToObject()},
   477  		{args: wrapArgs(newTestList(1, o, "foo")), want: newTestList(1, o, "foo").ToObject()},
   478  	}
   479  	for _, cas := range cases {
   480  		if err := runInvokeTestCase(fun, &cas); err != "" {
   481  			t.Error(err)
   482  		}
   483  	}
   484  }
   485  
   486  func TestListIteratorIter(t *testing.T) {
   487  	iter := newListIterator(NewList())
   488  	cas := &invokeTestCase{args: wrapArgs(iter), want: iter}
   489  	if err := runInvokeMethodTestCase(listIteratorType, "__iter__", cas); err != "" {
   490  		t.Error(err)
   491  	}
   492  }
   493  
   494  func TestListPop(t *testing.T) {
   495  	pop := mustNotRaise(GetAttr(NewRootFrame(), ListType.ToObject(), NewStr("pop"), nil))
   496  	fun := wrapFuncForTest(func(f *Frame, l *List, args ...*Object) (*Tuple, *BaseException) {
   497  		result, raised := pop.Call(f, append(Args{l.ToObject()}, args...), nil)
   498  		if raised != nil {
   499  			return nil, raised
   500  		}
   501  		return newTestTuple(result, l), nil
   502  	})
   503  	cases := []invokeTestCase{
   504  		{args: wrapArgs(newTestList(1)), want: newTestTuple(1, newTestList().ToObject()).ToObject()},
   505  		{args: wrapArgs(newTestList(1), 0), want: newTestTuple(1, newTestList().ToObject()).ToObject()},
   506  		{args: wrapArgs(newTestList(-1, 0, 1)), want: newTestTuple(1, newTestList(-1, 0).ToObject()).ToObject()},
   507  		{args: wrapArgs(newTestList(-1, 0, 1), 0), want: newTestTuple(-1, newTestList(0, 1).ToObject()).ToObject()},
   508  		{args: wrapArgs(newTestList(-1, 0, 1), NewLong(big.NewInt(1))), want: newTestTuple(0, newTestList(-1, 1).ToObject()).ToObject()},
   509  		{args: wrapArgs(newTestList(-1, 0, 1), None), wantExc: mustCreateException(TypeErrorType, "an integer is required")},
   510  		{args: wrapArgs(newTestList(-1, 0, 1), None), wantExc: mustCreateException(TypeErrorType, "an integer is required")},
   511  		{args: wrapArgs(newTestList(-1, 0, 1), 3), wantExc: mustCreateException(IndexErrorType, "list index out of range")},
   512  		{args: wrapArgs(newTestList()), wantExc: mustCreateException(IndexErrorType, "list index out of range")},
   513  		{args: wrapArgs(newTestList(), 0), wantExc: mustCreateException(IndexErrorType, "list index out of range")},
   514  		{args: wrapArgs(newTestList(), 1), wantExc: mustCreateException(IndexErrorType, "list index out of range")},
   515  	}
   516  	for _, cas := range cases {
   517  		if err := runInvokeTestCase(fun, &cas); err != "" {
   518  			t.Error(err)
   519  		}
   520  	}
   521  }
   522  
   523  func TestListSetItem(t *testing.T) {
   524  	fun := newBuiltinFunction("TestListSetItem", func(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   525  		// Check that there is at least one arg, but otherwise leave
   526  		// the validation to __setitem__.
   527  		if raised := checkFunctionVarArgs(f, "TestListSetItem", args, ObjectType); raised != nil {
   528  			return nil, raised
   529  		}
   530  		setitem, raised := GetAttr(f, args[0], NewStr("__setitem__"), nil)
   531  		if raised != nil {
   532  			return nil, raised
   533  		}
   534  		_, raised = setitem.Call(f, args[1:], nil)
   535  		if raised != nil {
   536  			return nil, raised
   537  		}
   538  		return args[0], nil
   539  	}).ToObject()
   540  	cases := []invokeTestCase{
   541  		{args: wrapArgs(newTestList("foo", "bar"), 1, None), want: newTestList("foo", None).ToObject()},
   542  		{args: wrapArgs(newTestList(1, 2, 3), newTestSlice(0), newTestList(0)), want: newTestList(0, 1, 2, 3).ToObject()},
   543  		{args: wrapArgs(newTestList(1, 2, 3), newTestSlice(1), newTestList(4)), want: newTestList(4, 2, 3).ToObject()},
   544  		{args: wrapArgs(newTestList(1, 2, 3), newTestSlice(2, None), newTestList("foo")), want: newTestList(1, 2, "foo").ToObject()},
   545  		{args: wrapArgs(newTestList(1, 2, 3), newTestSlice(100, None), newTestList("foo")), want: newTestList(1, 2, 3, "foo").ToObject()},
   546  		{args: wrapArgs(newTestList(1, 2, 4, 5), newTestSlice(1, None, 2), newTestTuple("foo", "bar")), want: newTestList(1, "foo", 4, "bar").ToObject()},
   547  		{args: wrapArgs(newTestList(1, 2, 3), newTestSlice(None, None, 2), newTestList("foo")), wantExc: mustCreateException(ValueErrorType, "attempt to assign sequence of size 1 to extended slice of size 2")},
   548  		{args: wrapArgs(newTestRange(100), newTestSlice(None, None), NewList()), want: NewList().ToObject()},
   549  		{args: wrapArgs(NewList(), newTestSlice(4, 8, 0), NewList()), wantExc: mustCreateException(ValueErrorType, "slice step cannot be zero")},
   550  		{args: wrapArgs(newTestList("foo", "bar"), -100, None), wantExc: mustCreateException(IndexErrorType, "index out of range")},
   551  		{args: wrapArgs(NewList(), 101, None), wantExc: mustCreateException(IndexErrorType, "index out of range")},
   552  		{args: wrapArgs(newTestList(true), None, false), wantExc: mustCreateException(TypeErrorType, "list indices must be integers, not NoneType")},
   553  	}
   554  	for _, cas := range cases {
   555  		if err := runInvokeTestCase(fun, &cas); err != "" {
   556  			t.Error(err)
   557  		}
   558  	}
   559  }
   560  
   561  func TestListSort(t *testing.T) {
   562  	sort := mustNotRaise(GetAttr(NewRootFrame(), ListType.ToObject(), NewStr("sort"), nil))
   563  	fun := newBuiltinFunction("TestListSort", func(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   564  		if _, raised := sort.Call(f, args, nil); raised != nil {
   565  			return nil, raised
   566  		}
   567  		return args[0], nil
   568  	}).ToObject()
   569  	cases := []invokeTestCase{
   570  		{args: wrapArgs(NewList()), want: NewList().ToObject()},
   571  		{args: wrapArgs(newTestList("foo", "bar")), want: newTestList("bar", "foo").ToObject()},
   572  		{args: wrapArgs(newTestList(true, false)), want: newTestList(false, true).ToObject()},
   573  		{args: wrapArgs(newTestList(1, 2, 0, 3)), want: newTestRange(4).ToObject()},
   574  		{args: wrapArgs(newTestRange(100)), want: newTestRange(100).ToObject()},
   575  		{args: wrapArgs(1), wantExc: mustCreateException(TypeErrorType, "unbound method sort() must be called with list instance as first argument (got int instance instead)")},
   576  		{args: wrapArgs(NewList(), 1), wantExc: mustCreateException(TypeErrorType, "'sort' of 'list' requires 1 arguments")},
   577  	}
   578  	for _, cas := range cases {
   579  		if err := runInvokeTestCase(fun, &cas); err != "" {
   580  			t.Error(err)
   581  		}
   582  	}
   583  }
   584  
   585  func newTestRange(n int) *List {
   586  	elems := make([]*Object, n)
   587  	for i := 0; i < n; i++ {
   588  		elems[i] = NewInt(i).ToObject()
   589  	}
   590  	return NewList(elems...)
   591  }
   592  
   593  func newTestList(elems ...interface{}) *List {
   594  	listElems, raised := seqWrapEach(NewRootFrame(), elems...)
   595  	if raised != nil {
   596  		panic(raised)
   597  	}
   598  	return NewList(listElems...)
   599  }