github.com/google/grumpy@v0.0.0-20171122020858-3ec87959189c/runtime/builtin_types_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  	"bytes"
    19  	"fmt"
    20  	"io"
    21  	"math/big"
    22  	"os"
    23  	"testing"
    24  )
    25  
    26  func TestBuiltinDelAttr(t *testing.T) {
    27  	f := NewRootFrame()
    28  	delattr := mustNotRaise(Builtins.GetItemString(f, "delattr"))
    29  	fooType := newTestClass("Foo", []*Type{ObjectType}, NewDict())
    30  	fooForDelAttr := newObject(fooType)
    31  	fooValue := newObject(ObjectType)
    32  	mustNotRaise(nil, SetAttr(f, fooForDelAttr, NewStr("bar"), fooValue))
    33  	fun := wrapFuncForTest(func(f *Frame, args ...*Object) (*Object, *BaseException) {
    34  		result, raised := delattr.Call(f, args, nil)
    35  		if raised != nil {
    36  			return nil, raised
    37  		}
    38  		val, raised := GetAttr(f, args[0], toStrUnsafe(args[1]), None)
    39  		return newTestTuple(result, val == fooValue).ToObject(), nil
    40  	})
    41  	cases := []invokeTestCase{
    42  		{args: wrapArgs(fooForDelAttr, "bar"), want: newTestTuple(None, False.ToObject()).ToObject()},
    43  		{args: wrapArgs(fooForDelAttr, "baz"), wantExc: mustCreateException(AttributeErrorType, "'Foo' object has no attribute 'baz'")},
    44  		{args: wrapArgs(fooForDelAttr), wantExc: mustCreateException(TypeErrorType, "'delattr' requires 2 arguments")},
    45  		{args: wrapArgs(fooForDelAttr, "foo", "bar"), wantExc: mustCreateException(TypeErrorType, "'delattr' requires 2 arguments")},
    46  	}
    47  	for _, cas := range cases {
    48  		if err := runInvokeTestCase(fun, &cas); err != "" {
    49  			t.Error(err)
    50  		}
    51  	}
    52  }
    53  
    54  func TestBuiltinFuncs(t *testing.T) {
    55  	f := NewRootFrame()
    56  	objectDir := ObjectType.Dict().Keys(f)
    57  	objectDir.Sort(f)
    58  	fooType := newTestClass("Foo", []*Type{ObjectType}, newStringDict(map[string]*Object{"bar": None}))
    59  	fooTypeDir := NewList(objectDir.elems...)
    60  	fooTypeDir.Append(NewStr("bar").ToObject())
    61  	fooTypeDir.Sort(f)
    62  	foo := newObject(fooType)
    63  	SetAttr(f, foo, NewStr("baz"), None)
    64  	fooDir := NewList(fooTypeDir.elems...)
    65  	fooDir.Append(NewStr("baz").ToObject())
    66  	fooDir.Sort(f)
    67  	dirModule := newTestModule("foo", "foo.py")
    68  	if raised := dirModule.Dict().SetItemString(NewRootFrame(), "bar", newObject(ObjectType)); raised != nil {
    69  		panic(raised)
    70  	}
    71  	dirModuleDir := dirModule.Dict().Keys(NewRootFrame())
    72  	if raised := dirModuleDir.Sort(NewRootFrame()); raised != nil {
    73  		panic(raised)
    74  	}
    75  	iter := mustNotRaise(Iter(f, mustNotRaise(xrangeType.Call(f, wrapArgs(5), nil))))
    76  	neg := wrapFuncForTest(func(f *Frame, i int) int { return -i })
    77  	raiseKey := wrapFuncForTest(func(f *Frame, o *Object) *BaseException { return f.RaiseType(RuntimeErrorType, "foo") })
    78  	hexOctType := newTestClass("HexOct", []*Type{ObjectType}, newStringDict(map[string]*Object{
    79  		"__hex__": newBuiltinFunction("__hex__", func(f *Frame, _ Args, _ KWArgs) (*Object, *BaseException) {
    80  			return NewStr("0xhexadecimal").ToObject(), nil
    81  		}).ToObject(),
    82  		"__oct__": newBuiltinFunction("__hex__", func(f *Frame, _ Args, _ KWArgs) (*Object, *BaseException) {
    83  			return NewStr("0octal").ToObject(), nil
    84  		}).ToObject(),
    85  	}))
    86  	badNonZeroType := newTestClass("BadNonZeroType", []*Type{ObjectType}, newStringDict(map[string]*Object{
    87  		"__nonzero__": newBuiltinFunction("__nonzero__", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
    88  			return nil, f.RaiseType(RuntimeErrorType, "foo")
    89  		}).ToObject(),
    90  	}))
    91  	badNextType := newTestClass("BadNextType", []*Type{ObjectType}, newStringDict(map[string]*Object{
    92  		"next": newBuiltinFunction("next", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
    93  			return nil, f.RaiseType(RuntimeErrorType, "foo")
    94  		}).ToObject(),
    95  	}))
    96  	badIterType := newTestClass("BadIterType", []*Type{ObjectType}, newStringDict(map[string]*Object{
    97  		"__iter__": newBuiltinFunction("__iter__", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
    98  			return newObject(badNextType), nil
    99  		}).ToObject(),
   100  	}))
   101  	addType := newTestClass("Add", []*Type{ObjectType}, newStringDict(map[string]*Object{
   102  		"__add__": newBuiltinFunction("__add__", func(f *Frame, _ Args, _ KWArgs) (*Object, *BaseException) {
   103  			return NewInt(1).ToObject(), nil
   104  		}).ToObject(),
   105  	}))
   106  	fooBuiltinFunc := newBuiltinFunction("foo", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
   107  		return newTestTuple(NewTuple(args.makeCopy()...), kwargs.makeDict()).ToObject(), nil
   108  	}).ToObject()
   109  	fooFunc := NewFunction(NewCode("foo", "foo.py", nil, CodeFlagVarArg, func(f *Frame, args []*Object) (*Object, *BaseException) {
   110  		return args[0], nil
   111  	}), nil)
   112  	cases := []struct {
   113  		f       string
   114  		args    Args
   115  		kwargs  KWArgs
   116  		want    *Object
   117  		wantExc *BaseException
   118  	}{
   119  		{f: "abs", args: wrapArgs(1, 2, 3), wantExc: mustCreateException(TypeErrorType, "'abs' requires 1 arguments")},
   120  		{f: "abs", args: wrapArgs(1), want: NewInt(1).ToObject()},
   121  		{f: "abs", args: wrapArgs(-1), want: NewInt(1).ToObject()},
   122  		{f: "abs", args: wrapArgs(big.NewInt(2)), want: NewLong(big.NewInt(2)).ToObject()},
   123  		{f: "abs", args: wrapArgs(big.NewInt(-2)), want: NewLong(big.NewInt(2)).ToObject()},
   124  		{f: "abs", args: wrapArgs(NewFloat(3.4)), want: NewFloat(3.4).ToObject()},
   125  		{f: "abs", args: wrapArgs(NewFloat(-3.4)), want: NewFloat(3.4).ToObject()},
   126  		{f: "abs", args: wrapArgs(MinInt), want: NewLong(big.NewInt(MinInt).Neg(minIntBig)).ToObject()},
   127  		{f: "abs", args: wrapArgs(NewStr("a")), wantExc: mustCreateException(TypeErrorType, "bad operand type for abs(): 'str'")},
   128  		{f: "all", args: wrapArgs(newTestList()), want: True.ToObject()},
   129  		{f: "all", args: wrapArgs(newTestList(1, 2, 3)), want: True.ToObject()},
   130  		{f: "all", args: wrapArgs(newTestList(1, 0, 1)), want: False.ToObject()},
   131  		{f: "all", args: wrapArgs(13), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")},
   132  		{f: "all", args: wrapArgs(newTestList(newObject(badNonZeroType))), wantExc: mustCreateException(RuntimeErrorType, "foo")},
   133  		{f: "all", args: wrapArgs(newObject(badIterType)), wantExc: mustCreateException(RuntimeErrorType, "foo")},
   134  		{f: "any", args: wrapArgs(newTestList()), want: False.ToObject()},
   135  		{f: "any", args: wrapArgs(newTestList(1, 2, 3)), want: True.ToObject()},
   136  		{f: "any", args: wrapArgs(newTestList(1, 0, 1)), want: True.ToObject()},
   137  		{f: "any", args: wrapArgs(newTestList(0, 0, 0)), want: False.ToObject()},
   138  		{f: "any", args: wrapArgs(newTestList(False.ToObject(), False.ToObject())), want: False.ToObject()},
   139  		{f: "any", args: wrapArgs(13), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")},
   140  		{f: "any", args: wrapArgs(newTestList(newObject(badNonZeroType))), wantExc: mustCreateException(RuntimeErrorType, "foo")},
   141  		{f: "any", args: wrapArgs(newObject(badIterType)), wantExc: mustCreateException(RuntimeErrorType, "foo")},
   142  		{f: "bin", args: wrapArgs(64 + 8 + 1), want: NewStr("0b1001001").ToObject()},
   143  		{f: "bin", args: wrapArgs(MinInt), want: NewStr(fmt.Sprintf("-0b%b0", -(MinInt >> 1))).ToObject()},
   144  		{f: "bin", args: wrapArgs(0), want: NewStr("0b0").ToObject()},
   145  		{f: "bin", args: wrapArgs(1), want: NewStr("0b1").ToObject()},
   146  		{f: "bin", args: wrapArgs(-1), want: NewStr("-0b1").ToObject()},
   147  		{f: "bin", args: wrapArgs(big.NewInt(-1)), want: NewStr("-0b1").ToObject()},
   148  		{f: "bin", args: wrapArgs("foo"), wantExc: mustCreateException(TypeErrorType, "str object cannot be interpreted as an index")},
   149  		{f: "bin", args: wrapArgs(0.1), wantExc: mustCreateException(TypeErrorType, "float object cannot be interpreted as an index")},
   150  		{f: "bin", args: wrapArgs(1, 2, 3), wantExc: mustCreateException(TypeErrorType, "'bin' requires 1 arguments")},
   151  		{f: "bin", args: wrapArgs(newTestIndexObject(123)), want: NewStr("0b1111011").ToObject()},
   152  		{f: "callable", args: wrapArgs(fooBuiltinFunc), want: True.ToObject()},
   153  		{f: "callable", args: wrapArgs(fooFunc), want: True.ToObject()},
   154  		{f: "callable", args: wrapArgs(0), want: False.ToObject()},
   155  		{f: "callable", args: wrapArgs(0.1), want: False.ToObject()},
   156  		{f: "callable", args: wrapArgs("foo"), want: False.ToObject()},
   157  		{f: "callable", args: wrapArgs(newTestDict("foo", 1, "bar", 2)), want: False.ToObject()},
   158  		{f: "callable", args: wrapArgs(newTestList(1, 2, 3)), want: False.ToObject()},
   159  		{f: "callable", args: wrapArgs(iter), want: False.ToObject()},
   160  		{f: "callable", args: wrapArgs(1, 2), wantExc: mustCreateException(TypeErrorType, "'callable' requires 1 arguments")},
   161  		{f: "chr", args: wrapArgs(0), want: NewStr("\x00").ToObject()},
   162  		{f: "chr", args: wrapArgs(65), want: NewStr("A").ToObject()},
   163  		{f: "chr", args: wrapArgs(300), wantExc: mustCreateException(ValueErrorType, "chr() arg not in range(256)")},
   164  		{f: "chr", args: wrapArgs(-1), wantExc: mustCreateException(ValueErrorType, "chr() arg not in range(256)")},
   165  		{f: "chr", args: wrapArgs(), wantExc: mustCreateException(TypeErrorType, "'chr' requires 1 arguments")},
   166  		{f: "dir", args: wrapArgs(newObject(ObjectType)), want: objectDir.ToObject()},
   167  		{f: "dir", args: wrapArgs(newObject(fooType)), want: fooTypeDir.ToObject()},
   168  		{f: "dir", args: wrapArgs(fooType), want: fooTypeDir.ToObject()},
   169  		{f: "dir", args: wrapArgs(foo), want: fooDir.ToObject()},
   170  		{f: "dir", args: wrapArgs(dirModule), want: dirModuleDir.ToObject()},
   171  		{f: "dir", args: wrapArgs(), wantExc: mustCreateException(TypeErrorType, "'dir' requires 1 arguments")},
   172  		{f: "divmod", args: wrapArgs(12, 7), want: NewTuple2(NewInt(1).ToObject(), NewInt(5).ToObject()).ToObject()},
   173  		{f: "divmod", args: wrapArgs(-12, 7), want: NewTuple2(NewInt(-2).ToObject(), NewInt(2).ToObject()).ToObject()},
   174  		{f: "divmod", args: wrapArgs(12, -7), want: NewTuple2(NewInt(-2).ToObject(), NewInt(-2).ToObject()).ToObject()},
   175  		{f: "divmod", args: wrapArgs(-12, -7), want: NewTuple2(NewInt(1).ToObject(), NewInt(-5).ToObject()).ToObject()},
   176  		{f: "divmod", args: wrapArgs(MaxInt, MinInt), want: NewTuple2(NewInt(-1).ToObject(), NewInt(-1).ToObject()).ToObject()},
   177  		{f: "divmod", args: wrapArgs(MinInt, MaxInt), want: NewTuple2(NewInt(-2).ToObject(), NewInt(MaxInt-1).ToObject()).ToObject()},
   178  		{f: "divmod", args: wrapArgs(MinInt, -1), want: NewTuple2(NewLong(new(big.Int).Neg(minIntBig)).ToObject(), NewLong(big.NewInt(0)).ToObject()).ToObject()},
   179  		{f: "divmod", args: wrapArgs(big.NewInt(12), big.NewInt(7)), want: NewTuple2(NewLong(big.NewInt(1)).ToObject(), NewLong(big.NewInt(5)).ToObject()).ToObject()},
   180  		{f: "divmod", args: wrapArgs(big.NewInt(-12), big.NewInt(7)), want: NewTuple2(NewLong(big.NewInt(-2)).ToObject(), NewLong(big.NewInt(2)).ToObject()).ToObject()},
   181  		{f: "divmod", args: wrapArgs(big.NewInt(12), big.NewInt(-7)), want: NewTuple2(NewLong(big.NewInt(-2)).ToObject(), NewLong(big.NewInt(-2)).ToObject()).ToObject()},
   182  		{f: "divmod", args: wrapArgs(big.NewInt(-12), big.NewInt(-7)), want: NewTuple2(NewLong(big.NewInt(1)).ToObject(), NewLong(big.NewInt(-5)).ToObject()).ToObject()},
   183  		{f: "divmod", args: wrapArgs(3.25, 1.0), want: NewTuple2(NewFloat(3.0).ToObject(), NewFloat(0.25).ToObject()).ToObject()},
   184  		{f: "divmod", args: wrapArgs(-3.25, 1.0), want: NewTuple2(NewFloat(-4.0).ToObject(), NewFloat(0.75).ToObject()).ToObject()},
   185  		{f: "divmod", args: wrapArgs(3.25, -1.0), want: NewTuple2(NewFloat(-4.0).ToObject(), NewFloat(-0.75).ToObject()).ToObject()},
   186  		{f: "divmod", args: wrapArgs(-3.25, -1.0), want: NewTuple2(NewFloat(3.0).ToObject(), NewFloat(-0.25).ToObject()).ToObject()},
   187  		{f: "divmod", args: wrapArgs(NewStr("a"), NewStr("b")), wantExc: mustCreateException(TypeErrorType, "unsupported operand type(s) for divmod(): 'str' and 'str'")},
   188  		{f: "divmod", args: wrapArgs(), wantExc: mustCreateException(TypeErrorType, "'divmod' requires 2 arguments")},
   189  		{f: "getattr", args: wrapArgs(None, NewStr("foo").ToObject(), NewStr("bar").ToObject()), want: NewStr("bar").ToObject()},
   190  		{f: "getattr", args: wrapArgs(None, NewStr("foo").ToObject()), wantExc: mustCreateException(AttributeErrorType, "'NoneType' object has no attribute 'foo'")},
   191  		{f: "hasattr", args: wrapArgs(newObject(ObjectType), NewStr("foo").ToObject()), want: False.ToObject()},
   192  		{f: "hasattr", args: wrapArgs(foo, NewStr("bar").ToObject()), want: True.ToObject()},
   193  		{f: "hasattr", args: wrapArgs(foo, NewStr("baz").ToObject()), want: True.ToObject()},
   194  		{f: "hasattr", args: wrapArgs(foo, NewStr("qux").ToObject()), want: False.ToObject()},
   195  		{f: "hash", args: wrapArgs(123), want: NewInt(123).ToObject()},
   196  		{f: "hash", args: wrapArgs("foo"), want: hashFoo},
   197  		{f: "hash", args: wrapArgs(NewList()), wantExc: mustCreateException(TypeErrorType, "unhashable type: 'list'")},
   198  		{f: "hex", args: wrapArgs(0x63adbeef), want: NewStr("0x63adbeef").ToObject()},
   199  		{f: "hex", args: wrapArgs(0), want: NewStr("0x0").ToObject()},
   200  		{f: "hex", args: wrapArgs(1), want: NewStr("0x1").ToObject()},
   201  		{f: "hex", args: wrapArgs(-1), want: NewStr("-0x1").ToObject()},
   202  		{f: "hex", args: wrapArgs(big.NewInt(-1)), want: NewStr("-0x1L").ToObject()},
   203  		{f: "hex", args: wrapArgs("foo"), wantExc: mustCreateException(TypeErrorType, "hex() argument can't be converted to hex")},
   204  		{f: "hex", args: wrapArgs(0.1), wantExc: mustCreateException(TypeErrorType, "hex() argument can't be converted to hex")},
   205  		{f: "hex", args: wrapArgs(1, 2, 3), wantExc: mustCreateException(TypeErrorType, "'hex' requires 1 arguments")},
   206  		{f: "hex", args: wrapArgs(newObject(hexOctType)), want: NewStr("0xhexadecimal").ToObject()},
   207  		{f: "id", args: wrapArgs(foo), want: NewInt(int(uintptr(foo.toPointer()))).ToObject()},
   208  		{f: "id", args: wrapArgs(), wantExc: mustCreateException(TypeErrorType, "'id' requires 1 arguments")},
   209  		{f: "isinstance", args: wrapArgs(NewInt(42).ToObject(), IntType.ToObject()), want: True.ToObject()},
   210  		{f: "isinstance", args: wrapArgs(NewStr("foo").ToObject(), TupleType.ToObject()), want: False.ToObject()},
   211  		{f: "isinstance", args: wrapArgs(), wantExc: mustCreateException(TypeErrorType, "'isinstance' requires 2 arguments")},
   212  		{f: "issubclass", args: wrapArgs(IntType, IntType), want: True.ToObject()},
   213  		{f: "issubclass", args: wrapArgs(fooType, IntType), want: False.ToObject()},
   214  		{f: "issubclass", args: wrapArgs(fooType, ObjectType), want: True.ToObject()},
   215  		{f: "issubclass", args: wrapArgs(FloatType, newTestTuple(IntType, StrType)), want: False.ToObject()},
   216  		{f: "issubclass", args: wrapArgs(FloatType, newTestTuple(IntType, FloatType)), want: True.ToObject()},
   217  		{f: "issubclass", args: wrapArgs(), wantExc: mustCreateException(TypeErrorType, "'issubclass' requires 2 arguments")},
   218  		{f: "iter", args: wrapArgs(iter), want: iter},
   219  		{f: "iter", args: wrapArgs(42), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")},
   220  		{f: "len", args: wrapArgs(newTestList(1, 2, 3)), want: NewInt(3).ToObject()},
   221  		{f: "len", args: wrapArgs(), wantExc: mustCreateException(TypeErrorType, "'len' requires 1 arguments")},
   222  		{f: "map", args: wrapArgs(), wantExc: mustCreateException(TypeErrorType, "map() requires at least two args")},
   223  		{f: "map", args: wrapArgs(StrType), wantExc: mustCreateException(TypeErrorType, "map() requires at least two args")},
   224  		{f: "map", args: wrapArgs(None, newTestList()), want: newTestList().ToObject()},
   225  		{f: "map", args: wrapArgs(None, newTestList(1, 2, 3)), want: newTestList(1, 2, 3).ToObject()},
   226  		{f: "map", args: wrapArgs(None, newTestDict("foo", 1, "bar", 3)), want: newTestList("foo", "bar").ToObject()},
   227  		{f: "map", args: wrapArgs(None, None), wantExc: mustCreateException(TypeErrorType, "'NoneType' object is not iterable")},
   228  		{f: "map", args: wrapArgs(StrType, None), wantExc: mustCreateException(TypeErrorType, "'NoneType' object is not iterable")},
   229  		{f: "map", args: wrapArgs(StrType, newTestList(), None), wantExc: mustCreateException(TypeErrorType, "'NoneType' object is not iterable")},
   230  		{f: "map", args: wrapArgs(newTestList(), newTestList(1, 2, 3)), wantExc: mustCreateException(TypeErrorType, "'list' object is not callable")},
   231  		{f: "map", args: wrapArgs(StrType, newTestList()), want: newTestList().ToObject()},
   232  		{f: "map", args: wrapArgs(StrType, newTestList(1, 2, 3)), want: newTestList("1", "2", "3").ToObject()},
   233  		{f: "map", args: wrapArgs(StrType, newTestList(-1, -2, -3)), want: newTestList("-1", "-2", "-3").ToObject()},
   234  		{f: "map", args: wrapArgs(IntType, newTestList("1", "2", "3")), want: newTestList(1, 2, 3).ToObject()},
   235  		{f: "map", args: wrapArgs(IntType, newTestList("-1", "-2", "-3")), want: newTestList(-1, -2, -3).ToObject()},
   236  		{f: "map", args: wrapArgs(IntType, "123"), want: newTestList(1, 2, 3).ToObject()},
   237  		{f: "map", args: wrapArgs(IntType, newTestDict("1", "11", "2", "22")), want: newTestList(1, 2).ToObject()},
   238  		{f: "map", args: wrapArgs(IntType, 1), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")},
   239  		{f: "map", args: wrapArgs(1, newTestList(1, 2, 3)), wantExc: mustCreateException(TypeErrorType, "'int' object is not callable")},
   240  		{f: "map", args: wrapArgs(StrType, newTestList(), 1), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")},
   241  		{f: "max", args: wrapArgs(2, 3, 1), want: NewInt(3).ToObject()},
   242  		{f: "max", args: wrapArgs("bar", "foo"), want: NewStr("foo").ToObject()},
   243  		{f: "max", args: wrapArgs(newTestList(2, 3, 1)), want: NewInt(3).ToObject()},
   244  		{f: "max", args: wrapArgs(newTestList("bar", "foo")), want: NewStr("foo").ToObject()},
   245  		{f: "max", args: wrapArgs(2, 3, 1), want: NewInt(3).ToObject()},
   246  		{f: "max", args: wrapArgs("bar", "foo"), want: NewStr("foo").ToObject()},
   247  		{f: "max", args: wrapArgs(newTestList(2, 3, 1)), want: NewInt(3).ToObject()},
   248  		{f: "max", args: wrapArgs(newTestList("bar", "foo")), want: NewStr("foo").ToObject()},
   249  		{f: "max", args: wrapArgs(2, 3, 1), kwargs: wrapKWArgs("key", neg), want: NewInt(1).ToObject()},
   250  		{f: "max", args: wrapArgs(1, 2, 3), kwargs: wrapKWArgs("key", neg), want: NewInt(1).ToObject()},
   251  		{f: "max", args: wrapArgs(newTestList(2, 3, 1)), kwargs: wrapKWArgs("key", neg), want: NewInt(1).ToObject()},
   252  		{f: "max", args: wrapArgs(newTestList(1, 2, 3)), kwargs: wrapKWArgs("key", neg), want: NewInt(1).ToObject()},
   253  		{f: "max", args: wrapArgs(2, 3, 1), kwargs: wrapKWArgs("key", neg), want: NewInt(1).ToObject()},
   254  		{f: "max", args: wrapArgs(1, 2, 3), kwargs: wrapKWArgs("key", neg), want: NewInt(1).ToObject()},
   255  		{f: "max", args: wrapArgs(newTestList(2, 3, 1)), kwargs: wrapKWArgs("key", neg), want: NewInt(1).ToObject()},
   256  		{f: "max", args: wrapArgs(newTestList(1, 2, 3)), kwargs: wrapKWArgs("key", neg), want: NewInt(1).ToObject()},
   257  		{f: "max", args: wrapArgs(newTestList("foo")), want: NewStr("foo").ToObject()},
   258  		{f: "max", args: wrapArgs(1), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")},
   259  		{f: "max", args: wrapArgs(), wantExc: mustCreateException(TypeErrorType, "'max' requires 1 arguments")},
   260  		{f: "max", args: wrapArgs(newTestList()), wantExc: mustCreateException(ValueErrorType, "max() arg is an empty sequence")},
   261  		{f: "max", args: wrapArgs(1, 2), kwargs: wrapKWArgs("key", raiseKey), wantExc: mustCreateException(RuntimeErrorType, "foo")},
   262  		{f: "min", args: wrapArgs(2, 3, 1), want: NewInt(1).ToObject()},
   263  		{f: "min", args: wrapArgs("bar", "foo"), want: NewStr("bar").ToObject()},
   264  		{f: "min", args: wrapArgs(newTestList(2, 3, 1)), want: NewInt(1).ToObject()},
   265  		{f: "min", args: wrapArgs(newTestList("bar", "foo")), want: NewStr("bar").ToObject()},
   266  		{f: "min", args: wrapArgs(2, 3, 1), want: NewInt(1).ToObject()},
   267  		{f: "min", args: wrapArgs("bar", "foo"), want: NewStr("bar").ToObject()},
   268  		{f: "min", args: wrapArgs(newTestList(2, 3, 1)), want: NewInt(1).ToObject()},
   269  		{f: "min", args: wrapArgs(newTestList("bar", "foo")), want: NewStr("bar").ToObject()},
   270  		{f: "min", args: wrapArgs(2, 3, 1), kwargs: wrapKWArgs("key", neg), want: NewInt(3).ToObject()},
   271  		{f: "min", args: wrapArgs(1, 2, 3), kwargs: wrapKWArgs("key", neg), want: NewInt(3).ToObject()},
   272  		{f: "min", args: wrapArgs(newTestList(2, 3, 1)), kwargs: wrapKWArgs("key", neg), want: NewInt(3).ToObject()},
   273  		{f: "min", args: wrapArgs(newTestList(1, 2, 3)), kwargs: wrapKWArgs("key", neg), want: NewInt(3).ToObject()},
   274  		{f: "min", args: wrapArgs(2, 3, 1), kwargs: wrapKWArgs("key", neg), want: NewInt(3).ToObject()},
   275  		{f: "min", args: wrapArgs(1, 2, 3), kwargs: wrapKWArgs("key", neg), want: NewInt(3).ToObject()},
   276  		{f: "min", args: wrapArgs(newTestList(2, 3, 1)), kwargs: wrapKWArgs("key", neg), want: NewInt(3).ToObject()},
   277  		{f: "min", args: wrapArgs(newTestList(1, 2, 3)), kwargs: wrapKWArgs("key", neg), want: NewInt(3).ToObject()},
   278  		{f: "min", args: wrapArgs(newTestList("foo")), want: NewStr("foo").ToObject()},
   279  		{f: "min", args: wrapArgs(1), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")},
   280  		{f: "min", args: wrapArgs(), wantExc: mustCreateException(TypeErrorType, "'min' requires 1 arguments")},
   281  		{f: "min", args: wrapArgs(newTestList()), wantExc: mustCreateException(ValueErrorType, "min() arg is an empty sequence")},
   282  		{f: "min", args: wrapArgs(1, 2), kwargs: wrapKWArgs("key", raiseKey), wantExc: mustCreateException(RuntimeErrorType, "foo")},
   283  		{f: "oct", args: wrapArgs(077), want: NewStr("077").ToObject()},
   284  		{f: "oct", args: wrapArgs(0), want: NewStr("0").ToObject()},
   285  		{f: "oct", args: wrapArgs(1), want: NewStr("01").ToObject()},
   286  		{f: "oct", args: wrapArgs(-1), want: NewStr("-01").ToObject()},
   287  		{f: "oct", args: wrapArgs(big.NewInt(-1)), want: NewStr("-01L").ToObject()},
   288  		{f: "oct", args: wrapArgs("foo"), wantExc: mustCreateException(TypeErrorType, "oct() argument can't be converted to oct")},
   289  		{f: "oct", args: wrapArgs(0.1), wantExc: mustCreateException(TypeErrorType, "oct() argument can't be converted to oct")},
   290  		{f: "oct", args: wrapArgs(1, 2, 3), wantExc: mustCreateException(TypeErrorType, "'oct' requires 1 arguments")},
   291  		{f: "oct", args: wrapArgs(newObject(hexOctType)), want: NewStr("0octal").ToObject()},
   292  		{f: "ord", args: wrapArgs("a"), want: NewInt(97).ToObject()},
   293  		{f: "ord", args: wrapArgs(NewUnicode("樂")), want: NewInt(63764).ToObject()},
   294  		{f: "ord", args: wrapArgs("foo"), wantExc: mustCreateException(ValueErrorType, "ord() expected a character, but string of length 3 found")},
   295  		{f: "ord", args: wrapArgs(NewUnicode("волн")), wantExc: mustCreateException(ValueErrorType, "ord() expected a character, but string of length 4 found")},
   296  		{f: "ord", args: wrapArgs(1, 2, 3), wantExc: mustCreateException(TypeErrorType, "'ord' requires 1 arguments")},
   297  		{f: "range", args: wrapArgs(), wantExc: mustCreateException(TypeErrorType, "'__new__' of 'int' requires 3 arguments")},
   298  		{f: "range", args: wrapArgs(3), want: newTestList(0, 1, 2).ToObject()},
   299  		{f: "range", args: wrapArgs(10, 0), want: NewList().ToObject()},
   300  		{f: "range", args: wrapArgs(-12, -23, -5), want: newTestList(-12, -17, -22).ToObject()},
   301  		{f: "repr", args: wrapArgs(123), want: NewStr("123").ToObject()},
   302  		{f: "repr", args: wrapArgs(NewUnicode("abc")), want: NewStr("u'abc'").ToObject()},
   303  		{f: "repr", args: wrapArgs(newTestTuple("foo", "bar")), want: NewStr("('foo', 'bar')").ToObject()},
   304  		{f: "repr", args: wrapArgs("a", "b", "c"), wantExc: mustCreateException(TypeErrorType, "'repr' requires 1 arguments")},
   305  		{f: "round", args: wrapArgs(1234.567), want: NewFloat(1235).ToObject()},
   306  		{f: "round", args: wrapArgs(1234.111), want: NewFloat(1234).ToObject()},
   307  		{f: "round", args: wrapArgs(-1234.567), want: NewFloat(-1235).ToObject()},
   308  		{f: "round", args: wrapArgs(-1234.111), want: NewFloat(-1234).ToObject()},
   309  		{f: "round", args: wrapArgs(1234.567, newTestIndexObject(0)), want: NewFloat(1235).ToObject()},
   310  		{f: "round", args: wrapArgs("foo"), wantExc: mustCreateException(TypeErrorType, "a float is required")},
   311  		{f: "round", args: wrapArgs(12.5, 0), want: NewFloat(13.0).ToObject()},
   312  		{f: "round", args: wrapArgs(-12.5, 0), want: NewFloat(-13.0).ToObject()},
   313  		{f: "round", args: wrapArgs(12.5, 3), want: NewFloat(12.5).ToObject()},
   314  		{f: "round", args: wrapArgs(1234.5, 1), want: NewFloat(1234.5).ToObject()},
   315  		{f: "round", args: wrapArgs(1234.5, 1), want: NewFloat(1234.5).ToObject()},
   316  		{f: "round", args: wrapArgs(1234.56, 1), want: NewFloat(1234.6).ToObject()},
   317  		{f: "round", args: wrapArgs(-1234.56, 1), want: NewFloat(-1234.6).ToObject()},
   318  		{f: "round", args: wrapArgs(-1234.56, -2), want: NewFloat(-1200.0).ToObject()},
   319  		{f: "round", args: wrapArgs(-1234.56, -8), want: NewFloat(0.0).ToObject()},
   320  		{f: "round", args: wrapArgs(63.4, -3), want: NewFloat(0.0).ToObject()},
   321  		{f: "round", args: wrapArgs(63.4, -2), want: NewFloat(100.0).ToObject()},
   322  		{f: "sorted", args: wrapArgs(NewList()), want: NewList().ToObject()},
   323  		{f: "sorted", args: wrapArgs(newTestList("foo", "bar")), want: newTestList("bar", "foo").ToObject()},
   324  		{f: "sorted", args: wrapArgs(newTestList(true, false)), want: newTestList(false, true).ToObject()},
   325  		{f: "sorted", args: wrapArgs(newTestList(1, 2, 0, 3)), want: newTestRange(4).ToObject()},
   326  		{f: "sorted", args: wrapArgs(newTestRange(100)), want: newTestRange(100).ToObject()},
   327  		{f: "sorted", args: wrapArgs(newTestTuple(1, 2, 0, 3)), want: newTestRange(4).ToObject()},
   328  		{f: "sorted", args: wrapArgs(newTestDict("foo", 1, "bar", 2)), want: newTestList("bar", "foo").ToObject()},
   329  		{f: "sorted", args: wrapArgs(1), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")},
   330  		{f: "sorted", args: wrapArgs(newTestList("foo", "bar"), 2), wantExc: mustCreateException(TypeErrorType, "'sorted' requires 1 arguments")},
   331  		{f: "sum", args: wrapArgs(newTestList(1, 2, 3, 4)), want: NewInt(10).ToObject()},
   332  		{f: "sum", args: wrapArgs(newTestList(1, 2), 3), want: NewFloat(6).ToObject()},
   333  		{f: "sum", args: wrapArgs(newTestList(2, 1.1)), want: NewFloat(3.1).ToObject()},
   334  		{f: "sum", args: wrapArgs(newTestList(2, 1.1, 2)), want: NewFloat(5.1).ToObject()},
   335  		{f: "sum", args: wrapArgs(newTestList(2, 1.1, 2.0)), want: NewFloat(5.1).ToObject()},
   336  		{f: "sum", args: wrapArgs(newTestList(1), newObject(addType)), want: NewInt(1).ToObject()},
   337  		{f: "sum", args: wrapArgs(newTestList(newObject(addType)), newObject(addType)), want: NewInt(1).ToObject()},
   338  		{f: "unichr", args: wrapArgs(0), want: NewUnicode("\x00").ToObject()},
   339  		{f: "unichr", args: wrapArgs(65), want: NewStr("A").ToObject()},
   340  		{f: "unichr", args: wrapArgs(0x120000), wantExc: mustCreateException(ValueErrorType, "unichr() arg not in range(0x10ffff)")},
   341  		{f: "unichr", args: wrapArgs(-1), wantExc: mustCreateException(ValueErrorType, "unichr() arg not in range(0x10ffff)")},
   342  		{f: "unichr", args: wrapArgs(), wantExc: mustCreateException(TypeErrorType, "'unichr' requires 1 arguments")},
   343  		{f: "zip", args: wrapArgs(), want: newTestList().ToObject()},
   344  		{f: "zip", args: wrapArgs(newTestTuple()), want: newTestList().ToObject()},
   345  		{f: "zip", args: wrapArgs(newTestList()), want: newTestList().ToObject()},
   346  		{f: "zip", args: wrapArgs(newTestList(1)), want: newTestList(newTestTuple(1).ToObject()).ToObject()},
   347  		{f: "zip", args: wrapArgs(newTestList(1, 2, 3)), want: newTestList(newTestTuple(1).ToObject(), newTestTuple(2).ToObject(), newTestTuple(3).ToObject()).ToObject()},
   348  		{f: "zip", args: wrapArgs(newTestRange(3)), want: newTestList(newTestTuple(0).ToObject(), newTestTuple(1).ToObject(), newTestTuple(2).ToObject()).ToObject()},
   349  		{f: "zip", args: wrapArgs(newTestTuple(1, 2, 3), newTestTuple(4, 5, 6)), want: NewList(newTestTuple(1, 4).ToObject(), newTestTuple(2, 5).ToObject(), newTestTuple(3, 6).ToObject()).ToObject()},
   350  		{f: "zip", args: wrapArgs(newTestTuple(1, 2, 3), newTestTuple(4, 5)), want: NewList(newTestTuple(1, 4).ToObject(), newTestTuple(2, 5).ToObject()).ToObject()},
   351  		{f: "zip", args: wrapArgs(newTestTuple(1, 2), newTestTuple(4, 5, 5)), want: NewList(newTestTuple(1, 4).ToObject(), newTestTuple(2, 5).ToObject()).ToObject()},
   352  		{f: "zip", args: wrapArgs(1), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")},
   353  		{f: "zip", args: wrapArgs(newTestDict("foo", 1, "bar", 2)), want: newTestList(newTestTuple("foo").ToObject(), newTestTuple("bar").ToObject()).ToObject()},
   354  	}
   355  	for _, cas := range cases {
   356  		fun := mustNotRaise(Builtins.GetItemString(NewRootFrame(), cas.f))
   357  		if fun == nil {
   358  			t.Fatalf("%s not found in builtins: %v", cas.f, Builtins)
   359  		}
   360  		testCase := invokeTestCase{args: cas.args, kwargs: cas.kwargs, want: cas.want, wantExc: cas.wantExc}
   361  		if err := runInvokeTestCase(fun, &testCase); err != "" {
   362  			t.Error(err)
   363  		}
   364  	}
   365  }
   366  
   367  func TestBuiltinGlobals(t *testing.T) {
   368  	f := NewRootFrame()
   369  	f.globals = newTestDict("foo", 1, "bar", 2, 42, None)
   370  	globals := mustNotRaise(Builtins.GetItemString(f, "globals"))
   371  	got, raised := globals.Call(f, nil, nil)
   372  	want := newTestDict("foo", 1, "bar", 2, 42, None).ToObject()
   373  	switch checkResult(got, want, raised, nil) {
   374  	case checkInvokeResultExceptionMismatch:
   375  		t.Errorf("globals() = %v, want %v", got, want)
   376  	case checkInvokeResultReturnValueMismatch:
   377  		t.Errorf("globals() raised %v, want nil", raised)
   378  	}
   379  }
   380  
   381  func TestEllipsisRepr(t *testing.T) {
   382  	cas := invokeTestCase{args: wrapArgs(Ellipsis), want: NewStr("Ellipsis").ToObject()}
   383  	if err := runInvokeMethodTestCase(EllipsisType, "__repr__", &cas); err != "" {
   384  		t.Error(err)
   385  	}
   386  }
   387  
   388  func TestNoneRepr(t *testing.T) {
   389  	cas := invokeTestCase{args: wrapArgs(None), want: NewStr("None").ToObject()}
   390  	if err := runInvokeMethodTestCase(NoneType, "__repr__", &cas); err != "" {
   391  		t.Error(err)
   392  	}
   393  }
   394  
   395  func TestNotImplementedRepr(t *testing.T) {
   396  	cas := invokeTestCase{args: wrapArgs(NotImplemented), want: NewStr("NotImplemented").ToObject()}
   397  	if err := runInvokeMethodTestCase(NotImplementedType, "__repr__", &cas); err != "" {
   398  		t.Error(err)
   399  	}
   400  }
   401  
   402  // captureStdout invokes a function closure which writes to stdout and captures
   403  // its output as string.
   404  func captureStdout(f *Frame, fn func() *BaseException) (string, *BaseException) {
   405  	r, w, err := os.Pipe()
   406  	if err != nil {
   407  		return "", f.RaiseType(RuntimeErrorType, fmt.Sprintf("failed to open pipe: %v", err))
   408  	}
   409  	oldStdout := Stdout
   410  	Stdout = NewFileFromFD(w.Fd(), nil)
   411  	defer func() {
   412  		Stdout = oldStdout
   413  	}()
   414  	done := make(chan struct{})
   415  	var raised *BaseException
   416  	go func() {
   417  		defer close(done)
   418  		defer w.Close()
   419  		raised = fn()
   420  	}()
   421  	var buf bytes.Buffer
   422  	if _, err := io.Copy(&buf, r); err != nil {
   423  		return "", f.RaiseType(RuntimeErrorType, fmt.Sprintf("failed to copy buffer: %v", err))
   424  	}
   425  	<-done
   426  	if raised != nil {
   427  		return "", raised
   428  	}
   429  	return buf.String(), nil
   430  }
   431  
   432  // TODO(corona10): Re-enable once #282 is addressed.
   433  /*func TestBuiltinPrint(t *testing.T) {
   434  	fun := wrapFuncForTest(func(f *Frame, args *Tuple, kwargs KWArgs) (string, *BaseException) {
   435  		return captureStdout(f, func() *BaseException {
   436  			_, raised := builtinPrint(NewRootFrame(), args.elems, kwargs)
   437  			return raised
   438  		})
   439  	})
   440  	cases := []invokeTestCase{
   441  		{args: wrapArgs(NewTuple(), wrapKWArgs()), want: NewStr("\n").ToObject()},
   442  		{args: wrapArgs(newTestTuple("abc"), wrapKWArgs()), want: NewStr("abc\n").ToObject()},
   443  		{args: wrapArgs(newTestTuple("abc", 123), wrapKWArgs()), want: NewStr("abc 123\n").ToObject()},
   444  		{args: wrapArgs(newTestTuple("abc", 123), wrapKWArgs("sep", "")), want: NewStr("abc123\n").ToObject()},
   445  		{args: wrapArgs(newTestTuple("abc", 123), wrapKWArgs("end", "")), want: NewStr("abc 123").ToObject()},
   446  		{args: wrapArgs(newTestTuple("abc", 123), wrapKWArgs("sep", "XX", "end", "--")), want: NewStr("abcXX123--").ToObject()},
   447  	}
   448  	for _, cas := range cases {
   449  		if err := runInvokeTestCase(fun, &cas); err != "" {
   450  			t.Error(err)
   451  		}
   452  	}
   453  }*/
   454  
   455  func TestBuiltinSetAttr(t *testing.T) {
   456  	setattr := mustNotRaise(Builtins.GetItemString(NewRootFrame(), "setattr"))
   457  	fooType := newTestClass("Foo", []*Type{ObjectType}, newStringDict(map[string]*Object{}))
   458  	foo := newObject(fooType)
   459  	fun := wrapFuncForTest(func(f *Frame, args ...*Object) (*Object, *BaseException) {
   460  		result, raised := setattr.Call(f, args, nil)
   461  		if raised != nil {
   462  			return nil, raised
   463  		}
   464  		val, raised := GetAttr(f, args[0], toStrUnsafe(args[1]), nil)
   465  		if raised != nil {
   466  			return nil, raised
   467  		}
   468  		return newTestTuple(result, val).ToObject(), nil
   469  	})
   470  	cases := []invokeTestCase{
   471  		{args: wrapArgs(foo), wantExc: mustCreateException(TypeErrorType, "'setattr' requires 3 arguments")},
   472  		{args: wrapArgs(newObject(fooType), "foo", "bar"), want: newTestTuple(None, "bar").ToObject()},
   473  		{args: wrapArgs(newObject(fooType), "foo", 123), want: newTestTuple(None, 123).ToObject()},
   474  		{args: wrapArgs(foo, "foo"), wantExc: mustCreateException(TypeErrorType, "'setattr' requires 3 arguments")},
   475  		{args: wrapArgs(foo, "foo", 123, None), wantExc: mustCreateException(TypeErrorType, "'setattr' requires 3 arguments")},
   476  		{args: wrapArgs(foo, 123, 123), wantExc: mustCreateException(TypeErrorType, "'setattr' requires a 'str' object but received a \"int\"")},
   477  	}
   478  	for _, cas := range cases {
   479  		if err := runInvokeTestCase(fun, &cas); err != "" {
   480  			t.Error(err)
   481  		}
   482  	}
   483  }
   484  
   485  // TODO(corona10): Re-enable once #282 is addressed.
   486  /*func TestRawInput(t *testing.T) {
   487  	fun := wrapFuncForTest(func(f *Frame, s string, args ...*Object) (*Object, *BaseException) {
   488  		// Create a fake Stdin for input test.
   489  		stdinFile, w, err := os.Pipe()
   490  		if err != nil {
   491  			return nil, f.RaiseType(RuntimeErrorType, fmt.Sprintf("failed to open pipe: %v", err))
   492  		}
   493  
   494  		go func() {
   495  			w.Write([]byte(s))
   496  			w.Close()
   497  		}()
   498  
   499  		oldStdin := Stdin
   500  		Stdin = NewFileFromFD(stdinFile.Fd(), nil)
   501  		defer func() {
   502  			Stdin = oldStdin
   503  			stdinFile.Close()
   504  		}()
   505  
   506  		var input *Object
   507  		output, raised := captureStdout(f, func() *BaseException {
   508  			in, raised := builtinRawInput(f, args, nil)
   509  			input = in
   510  			return raised
   511  		})
   512  
   513  		if raised != nil {
   514  			return nil, raised
   515  		}
   516  
   517  		return newTestTuple(input, output).ToObject(), nil
   518  	})
   519  
   520  	cases := []invokeTestCase{
   521  		{args: wrapArgs("HelloGrumpy\n", ""), want: newTestTuple("HelloGrumpy", "").ToObject()},
   522  		{args: wrapArgs("HelloGrumpy\n", "ShouldBeShown\nShouldBeShown\t"), want: newTestTuple("HelloGrumpy", "ShouldBeShown\nShouldBeShown\t").ToObject()},
   523  		{args: wrapArgs("HelloGrumpy\n", 5, 4), wantExc: mustCreateException(TypeErrorType, "[raw_]input expcted at most 1 arguments, got 2")},
   524  		{args: wrapArgs("HelloGrumpy\nHelloGrumpy\n", ""), want: newTestTuple("HelloGrumpy", "").ToObject()},
   525  		{args: wrapArgs("HelloGrumpy\nHelloGrumpy\n", "ShouldBeShown\nShouldBeShown\t"), want: newTestTuple("HelloGrumpy", "ShouldBeShown\nShouldBeShown\t").ToObject()},
   526  		{args: wrapArgs("HelloGrumpy\nHelloGrumpy\n", 5, 4), wantExc: mustCreateException(TypeErrorType, "[raw_]input expcted at most 1 arguments, got 2")},
   527  		{args: wrapArgs("", ""), wantExc: mustCreateException(EOFErrorType, "EOF when reading a line")},
   528  		{args: wrapArgs("", "ShouldBeShown\nShouldBeShown\t"), wantExc: mustCreateException(EOFErrorType, "EOF when reading a line")},
   529  		{args: wrapArgs("", 5, 4), wantExc: mustCreateException(TypeErrorType, "[raw_]input expcted at most 1 arguments, got 2")},
   530  	}
   531  
   532  	for _, cas := range cases {
   533  		if err := runInvokeTestCase(fun, &cas); err != "" {
   534  			t.Error(err)
   535  		}
   536  	}
   537  
   538  }*/
   539  
   540  func newTestIndexObject(index int) *Object {
   541  	indexType := newTestClass("Index", []*Type{ObjectType}, newStringDict(map[string]*Object{
   542  		"__index__": newBuiltinFunction("__index__", func(f *Frame, _ Args, _ KWArgs) (*Object, *BaseException) {
   543  			return NewInt(index).ToObject(), nil
   544  		}).ToObject(),
   545  	}))
   546  	return newObject(indexType)
   547  }