github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/runtime/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 grumpy
    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  }