github.com/pygolin/runtime@v0.0.0-20201208210830-a62e3cd39798/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 runtime 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 TestTupleIndex(t *testing.T) { 119 intIndexType := newTestClass("IntIndex", []*Type{ObjectType}, newStringDict(map[string]*Object{ 120 "__index__": newBuiltinFunction("__index__", func(f *Frame, _ Args, _ KWArgs) (*Object, *BaseException) { 121 return NewInt(0).ToObject(), nil 122 }).ToObject(), 123 })) 124 cases := []invokeTestCase{ 125 {args: wrapArgs(newTestTuple(), 1, "foo"), wantExc: mustCreateException(TypeErrorType, "slice indices must be integers or None or have an __index__ method")}, 126 {args: wrapArgs(newTestTuple(10, 20, 30), 20), want: NewInt(1).ToObject()}, 127 {args: wrapArgs(newTestTuple(10, 20, 30), 20, newObject(intIndexType)), want: NewInt(1).ToObject()}, 128 {args: wrapArgs(newTestTuple(0, "foo", "bar"), "foo"), want: NewInt(1).ToObject()}, 129 {args: wrapArgs(newTestTuple(0, 1, 2, 3, 4), 3, 3), want: NewInt(3).ToObject()}, 130 {args: wrapArgs(newTestTuple(0, 2.0, 2, 3, 4, 2, 1, "foo"), 3, 3), want: NewInt(3).ToObject()}, 131 {args: wrapArgs(newTestTuple(0, 1, 2, 3, 4), 3, 4), wantExc: mustCreateException(ValueErrorType, "3 is not in tuple")}, 132 {args: wrapArgs(newTestTuple(0, 1, 2, 3, 4), 3, 0, 4), want: NewInt(3).ToObject()}, 133 {args: wrapArgs(newTestTuple(0, 1, 2, 3, 4), 3, 0, 3), wantExc: mustCreateException(ValueErrorType, "3 is not in tuple")}, 134 {args: wrapArgs(newTestTuple(0, 1, 2, 3, 4), 3, -2), want: NewInt(3).ToObject()}, 135 {args: wrapArgs(newTestTuple(0, 1, 2, 3, 4), 3, -1), wantExc: mustCreateException(ValueErrorType, "3 is not in tuple")}, 136 {args: wrapArgs(newTestTuple(0, 1, 2, 3, 4), 3, 0, -1), want: NewInt(3).ToObject()}, 137 {args: wrapArgs(newTestTuple(0, 1, 2, 3, 4), 3, 0, -2), wantExc: mustCreateException(ValueErrorType, "3 is not in tuple")}, 138 {args: wrapArgs(newTestTuple(0, 1, 2, 3, 4), 3, 0, 999), want: NewInt(3).ToObject()}, 139 {args: wrapArgs(newTestTuple(0, 1, 2, 3, 4), "foo", 0, 999), wantExc: mustCreateException(ValueErrorType, "'foo' is not in tuple")}, 140 {args: wrapArgs(newTestTuple(0, 1, 2, 3, 4), 3, 999), wantExc: mustCreateException(ValueErrorType, "3 is not in tuple")}, 141 {args: wrapArgs(newTestTuple(0, 1, 2, 3, 4), 3, 5, 0), wantExc: mustCreateException(ValueErrorType, "3 is not in tuple")}, 142 } 143 for _, cas := range cases { 144 if err := runInvokeMethodTestCase(TupleType, "index", &cas); err != "" { 145 t.Error(err) 146 } 147 } 148 } 149 150 func BenchmarkTupleContains(b *testing.B) { 151 b.Run("false-3", func(b *testing.B) { 152 t := newTestTuple("foo", 42, "bar").ToObject() 153 a := wrapArgs(1)[0] 154 f := NewRootFrame() 155 b.ResetTimer() 156 for i := 0; i < b.N; i++ { 157 Contains(f, t, a) 158 } 159 }) 160 161 b.Run("false-10", func(b *testing.B) { 162 t := newTestTuple("foo", 42, "bar", "foo", 42, "bar", "foo", 42, "bar", "baz").ToObject() 163 a := wrapArgs(1)[0] 164 f := NewRootFrame() 165 b.ResetTimer() 166 for i := 0; i < b.N; i++ { 167 Contains(f, t, a) 168 } 169 }) 170 171 b.Run("true-3.1", func(b *testing.B) { 172 t := newTestTuple("foo", 42, "bar").ToObject() 173 a := wrapArgs("foo")[0] 174 f := NewRootFrame() 175 b.ResetTimer() 176 for i := 0; i < b.N; i++ { 177 Contains(f, t, a) 178 } 179 }) 180 181 b.Run("true-3.3", func(b *testing.B) { 182 t := newTestTuple("foo", 42, "bar").ToObject() 183 a := wrapArgs("bar")[0] 184 f := NewRootFrame() 185 b.ResetTimer() 186 for i := 0; i < b.N; i++ { 187 Contains(f, t, a) 188 } 189 }) 190 191 b.Run("true-10.10", func(b *testing.B) { 192 t := newTestTuple("foo", 42, "bar", "foo", 42, "bar", "foo", 42, "bar", "baz").ToObject() 193 a := wrapArgs("baz")[0] 194 f := NewRootFrame() 195 b.ResetTimer() 196 for i := 0; i < b.N; i++ { 197 Contains(f, t, a) 198 } 199 }) 200 } 201 202 func TestTupleGetItem(t *testing.T) { 203 cases := []invokeTestCase{ 204 {args: wrapArgs(newTestTuple("foo", 42, "bar"), 1), want: NewInt(42).ToObject()}, 205 {args: wrapArgs(newTestTuple("foo", 42, "bar"), -3), want: NewStr("foo").ToObject()}, 206 {args: wrapArgs(NewTuple(), newTestSlice(50, 100)), want: NewTuple().ToObject()}, 207 {args: wrapArgs(newTestTuple(1, 2, 3, 4, 5), newTestSlice(1, None, 2)), want: newTestTuple(2, 4).ToObject()}, 208 {args: wrapArgs(NewTuple(), 1), wantExc: mustCreateException(IndexErrorType, "index out of range")}, 209 {args: wrapArgs(newTestTuple(32), -100), wantExc: mustCreateException(IndexErrorType, "index out of range")}, 210 {args: wrapArgs(newTestTuple(1, 2, 3), newTestSlice(1, None, 0)), wantExc: mustCreateException(ValueErrorType, "slice step cannot be zero")}, 211 {args: wrapArgs(newTestTuple(true), None), wantExc: mustCreateException(TypeErrorType, "sequence indices must be integers, not NoneType")}, 212 } 213 for _, cas := range cases { 214 if err := runInvokeMethodTestCase(TupleType, "__getitem__", &cas); err != "" { 215 t.Error(err) 216 } 217 } 218 } 219 220 func TestTupleLen(t *testing.T) { 221 tuple := newTestTuple("foo", 42, "bar") 222 if got := tuple.Len(); got != 3 { 223 t.Errorf("%v.Len() = %v, want 3", tuple, got) 224 } 225 } 226 227 func TestTupleNew(t *testing.T) { 228 cases := []invokeTestCase{ 229 {want: NewTuple().ToObject()}, 230 {args: wrapArgs(newTestTuple(1, 2, 3)), want: newTestTuple(1, 2, 3).ToObject()}, 231 {args: wrapArgs(newTestDict(1, "foo", "bar", None)), want: newTestTuple(1, "bar").ToObject()}, 232 {args: wrapArgs(42), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")}, 233 } 234 for _, cas := range cases { 235 if err := runInvokeTestCase(TupleType.ToObject(), &cas); err != "" { 236 t.Error(err) 237 } 238 } 239 } 240 241 func TestTupleStrRepr(t *testing.T) { 242 fun := wrapFuncForTest(func(f *Frame, o *Object) (*Tuple, *BaseException) { 243 str, raised := ToStr(f, o) 244 if raised != nil { 245 return nil, raised 246 } 247 repr, raised := Repr(f, o) 248 if raised != nil { 249 return nil, raised 250 } 251 return newTestTuple(str, repr), nil 252 }) 253 cases := []invokeTestCase{ 254 {args: wrapArgs(NewTuple()), want: newTestTuple("()", "()").ToObject()}, 255 {args: wrapArgs(newTestTuple("foo")), want: newTestTuple("('foo',)", "('foo',)").ToObject()}, 256 {args: wrapArgs(newTestTuple(TupleType, ExceptionType)), want: newTestTuple("(<type 'tuple'>, <type 'Exception'>)", "(<type 'tuple'>, <type 'Exception'>)").ToObject()}, 257 } 258 for _, cas := range cases { 259 if err := runInvokeTestCase(fun, &cas); err != "" { 260 t.Error(err) 261 } 262 } 263 } 264 265 func TestTupleIter(t *testing.T) { 266 o := newObject(ObjectType) 267 cases := []invokeTestCase{ 268 {args: wrapArgs(NewTuple()), want: NewList().ToObject()}, 269 {args: wrapArgs(newTestTuple(1, o, "foo")), want: newTestList(1, o, "foo").ToObject()}, 270 } 271 for _, cas := range cases { 272 if err := runInvokeTestCase(ListType.ToObject(), &cas); err != "" { 273 t.Error(err) 274 } 275 } 276 } 277 278 func newTestTuple(elems ...interface{}) *Tuple { 279 return NewTuple(wrapArgs(elems...)...) 280 }