github.com/pygolin/runtime@v0.0.0-20201208210830-a62e3cd39798/method_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 "testing" 19 ) 20 21 func TestMethodCall(t *testing.T) { 22 foo := newBuiltinFunction("foo", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) { 23 return NewTuple(args.makeCopy()...).ToObject(), nil 24 }).ToObject() 25 self := newObject(ObjectType) 26 arg0 := NewInt(123).ToObject() 27 arg1 := NewStr("abc").ToObject() 28 cases := []invokeTestCase{ 29 {args: wrapArgs(newTestMethod(foo, self, ObjectType.ToObject())), want: NewTuple(self).ToObject()}, 30 {args: wrapArgs(newTestMethod(foo, None, ObjectType.ToObject()), self), want: NewTuple(self).ToObject()}, 31 {args: wrapArgs(newTestMethod(foo, self, ObjectType.ToObject()), arg0, arg1), want: NewTuple(self, arg0, arg1).ToObject()}, 32 {args: wrapArgs(newTestMethod(foo, None, ObjectType.ToObject()), self, arg0, arg1), want: NewTuple(self, arg0, arg1).ToObject()}, 33 {args: wrapArgs(), wantExc: mustCreateException(TypeErrorType, "unbound method __call__() must be called with instancemethod instance as first argument (got nothing instead)")}, 34 {args: wrapArgs(newObject(ObjectType)), wantExc: mustCreateException(TypeErrorType, "unbound method __call__() must be called with instancemethod instance as first argument (got object instance instead)")}, 35 {args: wrapArgs(newTestMethod(foo, None, IntType.ToObject()), newObject(ObjectType)), wantExc: mustCreateException(TypeErrorType, "unbound method foo() must be called with int instance as first argument (got object instance instead)")}, 36 {args: wrapArgs(newTestMethod(foo, None, IntType.ToObject())), wantExc: mustCreateException(TypeErrorType, "unbound method foo() must be called with int instance as first argument (got nothing instead)")}, 37 {args: wrapArgs(newTestMethod(foo, None, None), None), wantExc: mustCreateException(TypeErrorType, "classinfo must be a type or tuple of types")}, 38 } 39 for _, cas := range cases { 40 if err := runInvokeMethodTestCase(MethodType, "__call__", &cas); err != "" { 41 t.Error(err) 42 } 43 } 44 } 45 46 func TestMethodGet(t *testing.T) { 47 get := mustNotRaise(GetAttr(NewRootFrame(), MethodType.ToObject(), NewStr("__get__"), nil)) 48 fun := wrapFuncForTest(func(f *Frame, args ...*Object) (*Object, *BaseException) { 49 o, raised := get.Call(f, args, nil) 50 if raised != nil { 51 return nil, raised 52 } 53 m := toMethodUnsafe(o) 54 self, class := m.self, m.class 55 if self == nil { 56 self = None 57 } 58 if class == nil { 59 class = None 60 } 61 return newTestTuple(m.function, self, class).ToObject(), nil 62 }) 63 dummyFunc := wrapFuncForTest(func() {}) 64 bound := mustNotRaise(MethodType.Call(NewRootFrame(), wrapArgs(dummyFunc, "foo"), nil)) 65 unbound := newTestMethod(dummyFunc, None, IntType.ToObject()) 66 cases := []invokeTestCase{ 67 {args: wrapArgs(bound, "bar", StrType), want: newTestTuple(dummyFunc, "foo", None).ToObject()}, 68 {args: wrapArgs(unbound, "bar", StrType), want: newTestTuple(dummyFunc, None, IntType).ToObject()}, 69 {args: wrapArgs(unbound, 123, IntType), want: newTestTuple(dummyFunc, 123, IntType).ToObject()}, 70 {args: wrapArgs(newTestMethod(dummyFunc, None, None), "bar", StrType), wantExc: mustCreateException(TypeErrorType, "classinfo must be a type or tuple of types")}, 71 } 72 for _, cas := range cases { 73 if err := runInvokeTestCase(fun, &cas); err != "" { 74 t.Error(err) 75 } 76 } 77 } 78 79 func TestMethodNew(t *testing.T) { 80 cases := []invokeTestCase{ 81 {wantExc: mustCreateException(TypeErrorType, "'__new__' requires 3 arguments")}, 82 {args: Args{None, None, None}, wantExc: mustCreateException(TypeErrorType, "first argument must be callable")}, 83 {args: Args{wrapFuncForTest(func() {}), None}, wantExc: mustCreateException(TypeErrorType, "unbound methods must have non-NULL im_class")}, 84 } 85 for _, cas := range cases { 86 if err := runInvokeTestCase(MethodType.ToObject(), &cas); err != "" { 87 t.Error(err) 88 } 89 } 90 } 91 92 func TestMethodStrRepr(t *testing.T) { 93 foo := newBuiltinFunction("foo", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) { return None, nil }).ToObject() 94 cases := []invokeTestCase{ 95 {args: wrapArgs(newTestMethod(foo, None, StrType.ToObject())), want: NewStr("<unbound method str.foo>").ToObject()}, 96 {args: wrapArgs(newTestMethod(foo, NewStr("wut").ToObject(), StrType.ToObject())), want: NewStr("<bound method str.foo of 'wut'>").ToObject()}, 97 {args: wrapArgs(newTestMethod(foo, NewInt(123).ToObject(), TupleType.ToObject())), want: NewStr("<bound method tuple.foo of 123>").ToObject()}, 98 {args: wrapArgs(newTestMethod(foo, None, None)), want: NewStr("<unbound method ?.foo>").ToObject()}, 99 } 100 for _, cas := range cases { 101 if err := runInvokeTestCase(wrapFuncForTest(ToStr), &cas); err != "" { 102 t.Error(err) 103 } 104 if err := runInvokeTestCase(wrapFuncForTest(Repr), &cas); err != "" { 105 t.Error(err) 106 } 107 } 108 } 109 110 func newTestMethod(function, self, class *Object) *Method { 111 return toMethodUnsafe(mustNotRaise(MethodType.Call(NewRootFrame(), Args{function, self, class}, nil))) 112 }