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 }