github.com/google/grumpy@v0.0.0-20171122020858-3ec87959189c/runtime/tuple_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  	"reflect"
    19  	"testing"
    20  )
    21  
    22  func TestNewTuple(t *testing.T) {
    23  	cases := [][]*Object{
    24  		nil,
    25  		{newObject(ObjectType)},
    26  		{newObject(ObjectType), newObject(ObjectType)},
    27  	}
    28  	for _, args := range cases {
    29  		tuple := NewTuple(args...)
    30  		if !reflect.DeepEqual(tuple.elems, args) {
    31  			t.Errorf("NewTuple(%v) = %v, want %v", args, tuple.elems, args)
    32  		}
    33  	}
    34  }
    35  
    36  func TestTupleBinaryOps(t *testing.T) {
    37  	fun := wrapFuncForTest(func(f *Frame, fn binaryOpFunc, v, w *Object) (*Object, *BaseException) {
    38  		return fn(f, v, w)
    39  	})
    40  	cases := []invokeTestCase{
    41  		{args: wrapArgs(Add, newTestTuple(3), newTestTuple("foo")), want: newTestTuple(3, "foo").ToObject()},
    42  		{args: wrapArgs(Add, NewTuple(None), NewTuple()), want: NewTuple(None).ToObject()},
    43  		{args: wrapArgs(Add, NewTuple(), newObject(ObjectType)), wantExc: mustCreateException(TypeErrorType, "unsupported operand type(s) for +: 'tuple' and 'object'")},
    44  		{args: wrapArgs(Add, None, NewTuple()), wantExc: mustCreateException(TypeErrorType, "unsupported operand type(s) for +: 'NoneType' and 'tuple'")},
    45  		{args: wrapArgs(Mul, NewTuple(), 10), want: NewTuple().ToObject()},
    46  		{args: wrapArgs(Mul, newTestTuple("baz"), -2), want: NewTuple().ToObject()},
    47  		{args: wrapArgs(Mul, newTestTuple(None, None), 0), want: NewTuple().ToObject()},
    48  		{args: wrapArgs(Mul, newTestTuple(1, "bar"), 2), want: newTestTuple(1, "bar", 1, "bar").ToObject()},
    49  		{args: wrapArgs(Mul, 1, newTestTuple(1, "bar")), want: newTestTuple(1, "bar").ToObject()},
    50  		{args: wrapArgs(Mul, newObject(ObjectType), newTestTuple(newObject(ObjectType))), wantExc: mustCreateException(TypeErrorType, "unsupported operand type(s) for *: 'object' and 'tuple'")},
    51  		{args: wrapArgs(Mul, NewTuple(newObject(ObjectType)), NewTuple()), wantExc: mustCreateException(TypeErrorType, "unsupported operand type(s) for *: 'tuple' and 'tuple'")},
    52  		{args: wrapArgs(Mul, NewTuple(None, None), MaxInt), wantExc: mustCreateException(OverflowErrorType, "result too large")},
    53  	}
    54  	for _, cas := range cases {
    55  		if err := runInvokeTestCase(fun, &cas); err != "" {
    56  			t.Error(err)
    57  		}
    58  	}
    59  }
    60  
    61  func TestTupleCompare(t *testing.T) {
    62  	o := newObject(ObjectType)
    63  	cases := []invokeTestCase{
    64  		{args: wrapArgs(NewTuple(), NewTuple()), want: compareAllResultEq},
    65  		{args: wrapArgs(newTestTuple("foo", o), newTestTuple("foo", o)), want: compareAllResultEq},
    66  		{args: wrapArgs(newTestTuple(4), newTestTuple(3, 0)), want: compareAllResultGT},
    67  		{args: wrapArgs(newTestTuple(4), newTestTuple(4, 3, 0)), want: compareAllResultLT},
    68  		{args: wrapArgs(NewTuple(o), NewTuple()), want: compareAllResultGT},
    69  		{args: wrapArgs(NewTuple(o), newTestTuple("foo")), want: compareAllResultLT},
    70  	}
    71  	for _, cas := range cases {
    72  		if err := runInvokeTestCase(compareAll, &cas); err != "" {
    73  			t.Error(err)
    74  		}
    75  	}
    76  }
    77  
    78  func TestTupleCompareNotImplemented(t *testing.T) {
    79  	cas := invokeTestCase{args: wrapArgs(NewTuple(), 3), want: NotImplemented}
    80  	if err := runInvokeMethodTestCase(TupleType, "__eq__", &cas); err != "" {
    81  		t.Error(err)
    82  	}
    83  }
    84  
    85  func TestTupleContains(t *testing.T) {
    86  	cases := []invokeTestCase{
    87  		{args: wrapArgs(newTestTuple("foo", 42, "bar"), 1), want: False.ToObject()},
    88  		{args: wrapArgs(newTestTuple("foo", 42, "bar"), "foo"), want: True.ToObject()},
    89  		{args: wrapArgs(newTestTuple("foo", 42, "bar"), 42), want: True.ToObject()},
    90  		{args: wrapArgs(newTestTuple("foo", 42, "bar"), "bar"), want: True.ToObject()},
    91  		{args: wrapArgs(NewTuple(), newTestSlice(50, 100)), want: False.ToObject()},
    92  		{args: wrapArgs(newTestTuple(1, 2, 3, 4, 5), newTestSlice(1, None, 2)), want: False.ToObject()},
    93  		{args: wrapArgs(NewTuple(), 1), want: False.ToObject()},
    94  		{args: wrapArgs(newTestTuple(32), -100), want: False.ToObject()},
    95  		{args: wrapArgs(newTestTuple(1, 2, 3), newTestSlice(1, None, 0)), want: False.ToObject()},
    96  		{args: wrapArgs(newTestTuple(true), None), want: False.ToObject()},
    97  	}
    98  	for _, cas := range cases {
    99  		if err := runInvokeMethodTestCase(TupleType, "__contains__", &cas); err != "" {
   100  			t.Error(err)
   101  		}
   102  	}
   103  }
   104  
   105  func TestTupleCount(t *testing.T) {
   106  	cases := []invokeTestCase{
   107  		{args: wrapArgs(NewTuple(), NewInt(1)), want: NewInt(0).ToObject()},
   108  		{args: wrapArgs(NewTuple(None, None, None), None), want: NewInt(3).ToObject()},
   109  		{args: wrapArgs(NewTuple()), wantExc: mustCreateException(TypeErrorType, "'count' of 'tuple' requires 2 arguments")},
   110  	}
   111  	for _, cas := range cases {
   112  		if err := runInvokeMethodTestCase(TupleType, "count", &cas); err != "" {
   113  			t.Error(err)
   114  		}
   115  	}
   116  }
   117  
   118  func BenchmarkTupleContains(b *testing.B) {
   119  	b.Run("false-3", func(b *testing.B) {
   120  		t := newTestTuple("foo", 42, "bar").ToObject()
   121  		a := wrapArgs(1)[0]
   122  		f := NewRootFrame()
   123  		b.ResetTimer()
   124  		for i := 0; i < b.N; i++ {
   125  			Contains(f, t, a)
   126  		}
   127  	})
   128  
   129  	b.Run("false-10", func(b *testing.B) {
   130  		t := newTestTuple("foo", 42, "bar", "foo", 42, "bar", "foo", 42, "bar", "baz").ToObject()
   131  		a := wrapArgs(1)[0]
   132  		f := NewRootFrame()
   133  		b.ResetTimer()
   134  		for i := 0; i < b.N; i++ {
   135  			Contains(f, t, a)
   136  		}
   137  	})
   138  
   139  	b.Run("true-3.1", func(b *testing.B) {
   140  		t := newTestTuple("foo", 42, "bar").ToObject()
   141  		a := wrapArgs("foo")[0]
   142  		f := NewRootFrame()
   143  		b.ResetTimer()
   144  		for i := 0; i < b.N; i++ {
   145  			Contains(f, t, a)
   146  		}
   147  	})
   148  
   149  	b.Run("true-3.3", func(b *testing.B) {
   150  		t := newTestTuple("foo", 42, "bar").ToObject()
   151  		a := wrapArgs("bar")[0]
   152  		f := NewRootFrame()
   153  		b.ResetTimer()
   154  		for i := 0; i < b.N; i++ {
   155  			Contains(f, t, a)
   156  		}
   157  	})
   158  
   159  	b.Run("true-10.10", func(b *testing.B) {
   160  		t := newTestTuple("foo", 42, "bar", "foo", 42, "bar", "foo", 42, "bar", "baz").ToObject()
   161  		a := wrapArgs("baz")[0]
   162  		f := NewRootFrame()
   163  		b.ResetTimer()
   164  		for i := 0; i < b.N; i++ {
   165  			Contains(f, t, a)
   166  		}
   167  	})
   168  }
   169  
   170  func TestTupleGetItem(t *testing.T) {
   171  	cases := []invokeTestCase{
   172  		{args: wrapArgs(newTestTuple("foo", 42, "bar"), 1), want: NewInt(42).ToObject()},
   173  		{args: wrapArgs(newTestTuple("foo", 42, "bar"), -3), want: NewStr("foo").ToObject()},
   174  		{args: wrapArgs(NewTuple(), newTestSlice(50, 100)), want: NewTuple().ToObject()},
   175  		{args: wrapArgs(newTestTuple(1, 2, 3, 4, 5), newTestSlice(1, None, 2)), want: newTestTuple(2, 4).ToObject()},
   176  		{args: wrapArgs(NewTuple(), 1), wantExc: mustCreateException(IndexErrorType, "index out of range")},
   177  		{args: wrapArgs(newTestTuple(32), -100), wantExc: mustCreateException(IndexErrorType, "index out of range")},
   178  		{args: wrapArgs(newTestTuple(1, 2, 3), newTestSlice(1, None, 0)), wantExc: mustCreateException(ValueErrorType, "slice step cannot be zero")},
   179  		{args: wrapArgs(newTestTuple(true), None), wantExc: mustCreateException(TypeErrorType, "sequence indices must be integers, not NoneType")},
   180  	}
   181  	for _, cas := range cases {
   182  		if err := runInvokeMethodTestCase(TupleType, "__getitem__", &cas); err != "" {
   183  			t.Error(err)
   184  		}
   185  	}
   186  }
   187  
   188  func TestTupleLen(t *testing.T) {
   189  	tuple := newTestTuple("foo", 42, "bar")
   190  	if got := tuple.Len(); got != 3 {
   191  		t.Errorf("%v.Len() = %v, want 3", tuple, got)
   192  	}
   193  }
   194  
   195  func TestTupleNew(t *testing.T) {
   196  	cases := []invokeTestCase{
   197  		{want: NewTuple().ToObject()},
   198  		{args: wrapArgs(newTestTuple(1, 2, 3)), want: newTestTuple(1, 2, 3).ToObject()},
   199  		{args: wrapArgs(newTestDict(1, "foo", "bar", None)), want: newTestTuple(1, "bar").ToObject()},
   200  		{args: wrapArgs(42), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")},
   201  	}
   202  	for _, cas := range cases {
   203  		if err := runInvokeTestCase(TupleType.ToObject(), &cas); err != "" {
   204  			t.Error(err)
   205  		}
   206  	}
   207  }
   208  
   209  func TestTupleStrRepr(t *testing.T) {
   210  	fun := wrapFuncForTest(func(f *Frame, o *Object) (*Tuple, *BaseException) {
   211  		str, raised := ToStr(f, o)
   212  		if raised != nil {
   213  			return nil, raised
   214  		}
   215  		repr, raised := Repr(f, o)
   216  		if raised != nil {
   217  			return nil, raised
   218  		}
   219  		return newTestTuple(str, repr), nil
   220  	})
   221  	cases := []invokeTestCase{
   222  		{args: wrapArgs(NewTuple()), want: newTestTuple("()", "()").ToObject()},
   223  		{args: wrapArgs(newTestTuple("foo")), want: newTestTuple("('foo',)", "('foo',)").ToObject()},
   224  		{args: wrapArgs(newTestTuple(TupleType, ExceptionType)), want: newTestTuple("(<type 'tuple'>, <type 'Exception'>)", "(<type 'tuple'>, <type 'Exception'>)").ToObject()},
   225  	}
   226  	for _, cas := range cases {
   227  		if err := runInvokeTestCase(fun, &cas); err != "" {
   228  			t.Error(err)
   229  		}
   230  	}
   231  }
   232  
   233  func TestTupleIter(t *testing.T) {
   234  	o := newObject(ObjectType)
   235  	cases := []invokeTestCase{
   236  		{args: wrapArgs(NewTuple()), want: NewList().ToObject()},
   237  		{args: wrapArgs(newTestTuple(1, o, "foo")), want: newTestList(1, o, "foo").ToObject()},
   238  	}
   239  	for _, cas := range cases {
   240  		if err := runInvokeTestCase(ListType.ToObject(), &cas); err != "" {
   241  			t.Error(err)
   242  		}
   243  	}
   244  }
   245  
   246  func newTestTuple(elems ...interface{}) *Tuple {
   247  	return NewTuple(wrapArgs(elems...)...)
   248  }