github.com/pygolin/runtime@v0.0.0-20201208210830-a62e3cd39798/function_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 "regexp" 19 "testing" 20 ) 21 22 func TestFunctionCall(t *testing.T) { 23 foo := newBuiltinFunction("foo", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) { 24 return newTestTuple(NewTuple(args.makeCopy()...), kwargs.makeDict()).ToObject(), nil 25 }).ToObject() 26 bar := NewFunction(NewCode("bar", "bar.py", nil, CodeFlagVarArg, func(f *Frame, args []*Object) (*Object, *BaseException) { 27 return args[0], nil 28 }), nil) 29 cases := []invokeTestCase{ 30 {args: wrapArgs(foo, 123, "abc"), kwargs: wrapKWArgs("b", "bear"), want: newTestTuple(newTestTuple(123, "abc"), newTestDict("b", "bear")).ToObject()}, 31 {args: wrapArgs(bar, "bar", "baz"), want: newTestTuple("bar", "baz").ToObject()}, 32 {wantExc: mustCreateException(TypeErrorType, "unbound method __call__() must be called with function instance as first argument (got nothing instead)")}, 33 {args: wrapArgs(newObject(ObjectType)), wantExc: mustCreateException(TypeErrorType, "unbound method __call__() must be called with function instance as first argument (got object instance instead)")}, 34 } 35 for _, cas := range cases { 36 if err := runInvokeMethodTestCase(FunctionType, "__call__", &cas); err != "" { 37 t.Error(err) 38 } 39 } 40 } 41 42 func TestFunctionGet(t *testing.T) { 43 appendMethod := mustNotRaise(GetAttr(NewRootFrame(), NewList().ToObject(), NewStr("append"), nil)) 44 if !appendMethod.isInstance(MethodType) { 45 t.Errorf("list.append = %v, want instancemethod", appendMethod) 46 } 47 } 48 49 func TestFunctionName(t *testing.T) { 50 fun := newBuiltinFunction("TestFunctionName", func(f *Frame, _ Args, _ KWArgs) (*Object, *BaseException) { 51 foo := newBuiltinFunction("foo", func(*Frame, Args, KWArgs) (*Object, *BaseException) { return None, nil }) 52 return GetAttr(f, foo.ToObject(), internedName, nil) 53 }).ToObject() 54 if err := runInvokeTestCase(fun, &invokeTestCase{want: NewStr("foo").ToObject()}); err != "" { 55 t.Error(err) 56 } 57 } 58 59 func TestFunctionStrRepr(t *testing.T) { 60 fn := func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) { return nil, nil } 61 cases := []struct { 62 o *Object 63 wantPattern string 64 }{ 65 {newBuiltinFunction("foo", fn).ToObject(), `^<function foo at \w+>$`}, 66 {newBuiltinFunction("some big function name", fn).ToObject(), `^<function some big function name at \w+>$`}, 67 } 68 for _, cas := range cases { 69 fun := wrapFuncForTest(func(f *Frame) *BaseException { 70 re := regexp.MustCompile(cas.wantPattern) 71 s, raised := ToStr(f, cas.o) 72 if raised != nil { 73 return raised 74 } 75 if !re.MatchString(s.Value()) { 76 t.Errorf("str(%v) = %v, want %q", cas.o, s, re) 77 } 78 s, raised = Repr(f, cas.o) 79 if raised != nil { 80 return raised 81 } 82 if !re.MatchString(s.Value()) { 83 t.Errorf("repr(%v) = %v, want %q", cas.o, s, re) 84 } 85 return nil 86 }) 87 if err := runInvokeTestCase(fun, &invokeTestCase{want: None}); err != "" { 88 t.Error(err) 89 } 90 } 91 } 92 93 func TestStaticMethodGet(t *testing.T) { 94 cases := []invokeTestCase{ 95 {args: wrapArgs(newStaticMethod(NewStr("abc").ToObject()), 123, IntType), want: NewStr("abc").ToObject()}, 96 {args: wrapArgs(newStaticMethod(nil), 123, IntType), wantExc: mustCreateException(RuntimeErrorType, "uninitialized staticmethod object")}, 97 } 98 for _, cas := range cases { 99 if err := runInvokeMethodTestCase(StaticMethodType, "__get__", &cas); err != "" { 100 t.Error(err) 101 } 102 } 103 } 104 105 func TestStaticMethodInit(t *testing.T) { 106 fun := wrapFuncForTest(func(f *Frame, args ...*Object) (*Object, *BaseException) { 107 m, raised := StaticMethodType.Call(f, args, nil) 108 if raised != nil { 109 return nil, raised 110 } 111 get, raised := GetAttr(f, m, NewStr("__get__"), nil) 112 if raised != nil { 113 return nil, raised 114 } 115 return get.Call(f, wrapArgs(123, IntType), nil) 116 }) 117 cases := []invokeTestCase{ 118 {args: wrapArgs(3.14), want: NewFloat(3.14).ToObject()}, 119 {wantExc: mustCreateException(TypeErrorType, "'__init__' requires 1 arguments")}, 120 } 121 for _, cas := range cases { 122 if err := runInvokeTestCase(fun, &cas); err != "" { 123 t.Error(err) 124 } 125 } 126 } 127 128 func TestClassMethodGet(t *testing.T) { 129 fun := wrapFuncForTest(func(f *Frame, meth *classMethod, args ...*Object) (*Object, *BaseException) { 130 get, raised := GetAttr(f, meth.ToObject(), NewStr("__get__"), nil) 131 if raised != nil { 132 return nil, raised 133 } 134 callable, raised := get.Call(f, args, nil) 135 if raised != nil { 136 return nil, raised 137 } 138 return callable.Call(f, nil, nil) 139 }) 140 echoFunc := wrapFuncForTest(func(f *Frame, args ...*Object) *Tuple { 141 return NewTuple(args...) 142 }) 143 cases := []invokeTestCase{ 144 {args: wrapArgs(newClassMethod(echoFunc), ObjectType, ObjectType), want: NewTuple(ObjectType.ToObject()).ToObject()}, 145 {args: wrapArgs(newClassMethod(NewStr("abc").ToObject()), 123, IntType), wantExc: mustCreateException(TypeErrorType, "first argument must be callable")}, 146 {args: wrapArgs(newClassMethod(nil), 123, IntType), wantExc: mustCreateException(RuntimeErrorType, "uninitialized classmethod object")}, 147 } 148 for _, cas := range cases { 149 if err := runInvokeTestCase(fun, &cas); err != "" { 150 t.Error(err) 151 } 152 } 153 } 154 155 func TestClassMethodInit(t *testing.T) { 156 fun := wrapFuncForTest(func(f *Frame, args ...*Object) (*Object, *BaseException) { 157 m, raised := ClassMethodType.Call(f, args, nil) 158 if raised != nil { 159 return nil, raised 160 } 161 get, raised := GetAttr(f, m, NewStr("__get__"), nil) 162 if raised != nil { 163 return nil, raised 164 } 165 return get.Call(f, wrapArgs(123, IntType), nil) 166 }) 167 cases := []invokeTestCase{ 168 // {args: wrapArgs(3.14), want: NewFloat(3.14).ToObject()}, 169 {wantExc: mustCreateException(TypeErrorType, "'__init__' requires 1 arguments")}, 170 } 171 for _, cas := range cases { 172 if err := runInvokeTestCase(fun, &cas); err != "" { 173 t.Error(err) 174 } 175 } 176 }