github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/runtime/set_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  	"fmt"
    19  	"testing"
    20  )
    21  
    22  func TestSetAdd(t *testing.T) {
    23  	fun := wrapFuncForTest(func(f *Frame, s *Set, args ...*Object) (*Object, *BaseException) {
    24  		add, raised := GetAttr(f, s.ToObject(), NewStr("add"), nil)
    25  		if raised != nil {
    26  			return nil, raised
    27  		}
    28  		if _, raised := add.Call(f, args, nil); raised != nil {
    29  			return nil, raised
    30  		}
    31  		return s.ToObject(), nil
    32  	})
    33  	cases := []invokeTestCase{
    34  		{args: wrapArgs(NewSet(), "foo"), want: newTestSet("foo").ToObject()},
    35  		{args: wrapArgs(newTestSet(1, 2, 3), 2), want: newTestSet(1, 2, 3).ToObject()},
    36  		{args: wrapArgs(NewSet(), NewList()), wantExc: mustCreateException(TypeErrorType, "unhashable type: 'list'")},
    37  		{args: wrapArgs(NewSet(), "foo", "bar"), wantExc: mustCreateException(TypeErrorType, "'add' of 'set' requires 2 arguments")},
    38  	}
    39  	for _, cas := range cases {
    40  		if err := runInvokeTestCase(fun, &cas); err != "" {
    41  			t.Error(err)
    42  		}
    43  	}
    44  }
    45  
    46  func TestSetContains(t *testing.T) {
    47  	f := NewRootFrame()
    48  	for _, typ := range []*Type{SetType, FrozenSetType} {
    49  		cases := []invokeTestCase{
    50  			{args: wrapArgs(mustNotRaise(typ.Call(f, nil, nil)), "foo"), want: False.ToObject()},
    51  			{args: wrapArgs(mustNotRaise(typ.Call(f, wrapArgs(newTestTuple(1, 2)), nil)), 2), want: True.ToObject()},
    52  			{args: wrapArgs(mustNotRaise(typ.Call(f, wrapArgs(newTestTuple(3, "foo")), nil)), 42), want: False.ToObject()},
    53  			{args: wrapArgs(mustNotRaise(typ.Call(f, nil, nil)), NewList()), wantExc: mustCreateException(TypeErrorType, "unhashable type: 'list'")},
    54  		}
    55  		for _, cas := range cases {
    56  			if err := runInvokeMethodTestCase(typ, "__contains__", &cas); err != "" {
    57  				t.Error(err)
    58  			}
    59  		}
    60  	}
    61  }
    62  
    63  func TestSetDiscard(t *testing.T) {
    64  	fun := wrapFuncForTest(func(f *Frame, s *Set, args ...*Object) (*Object, *BaseException) {
    65  		discard, raised := GetAttr(f, s.ToObject(), NewStr("discard"), nil)
    66  		if raised != nil {
    67  			return nil, raised
    68  		}
    69  		if _, raised := discard.Call(f, args, nil); raised != nil {
    70  			return nil, raised
    71  		}
    72  		return s.ToObject(), nil
    73  	})
    74  	cases := []invokeTestCase{
    75  		{args: wrapArgs(newTestSet(1, 2, 3), 2), want: newTestSet(1, 3).ToObject()},
    76  		{args: wrapArgs(newTestSet("foo", 3), "foo"), want: newTestSet(3).ToObject()},
    77  		{args: wrapArgs(NewSet(), NewList()), wantExc: mustCreateException(TypeErrorType, "unhashable type: 'list'")},
    78  		{args: wrapArgs(NewSet(), "foo", "bar"), wantExc: mustCreateException(TypeErrorType, "'discard' of 'set' requires 2 arguments")},
    79  	}
    80  	for _, cas := range cases {
    81  		if err := runInvokeTestCase(fun, &cas); err != "" {
    82  			t.Error(err)
    83  		}
    84  	}
    85  }
    86  
    87  func TestSetCompare(t *testing.T) {
    88  	modifiedSet := newTestSet(0)
    89  	modifiedType := newTestClass("Foo", []*Type{IntType}, newStringDict(map[string]*Object{
    90  		"__eq__": newBuiltinFunction("__eq__", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
    91  			modifiedSet.Add(f, NewStr("baz").ToObject())
    92  			return False.ToObject(), nil
    93  		}).ToObject(),
    94  	}))
    95  	cases := []invokeTestCase{
    96  		{args: wrapArgs(NewSet(), newTestSet("foo")), want: compareAllResultLT},
    97  		{args: wrapArgs(newTestSet(1, 2, 3), newTestSet(3, 2, 1)), want: compareAllResultEq},
    98  		{args: wrapArgs(newTestSet("foo", 3.14), newObject(ObjectType)), want: newTestTuple(false, false, false, true, true, true).ToObject()},
    99  		{args: wrapArgs(123, newTestSet("baz")), want: newTestTuple(true, true, false, true, false, false).ToObject()},
   100  		{args: wrapArgs(mustNotRaise(SetType.Call(NewRootFrame(), wrapArgs(newTestRange(100)), nil)), mustNotRaise(SetType.Call(NewRootFrame(), wrapArgs(newTestRange(100)), nil))), want: compareAllResultEq},
   101  		{args: wrapArgs(modifiedSet, newTestSet(newObject(modifiedType))), wantExc: mustCreateException(RuntimeErrorType, "set changed during iteration")},
   102  		{args: wrapArgs(newTestFrozenSet(), newTestFrozenSet("foo")), want: compareAllResultLT},
   103  		{args: wrapArgs(newTestFrozenSet(1, 2, 3), newTestFrozenSet(3, 2, 1)), want: compareAllResultEq},
   104  		{args: wrapArgs(newTestFrozenSet("foo", 3.14), newObject(ObjectType)), want: newTestTuple(true, true, false, true, false, false).ToObject()},
   105  		{args: wrapArgs(123, newTestFrozenSet("baz")), want: newTestTuple(false, false, false, true, true, true).ToObject()},
   106  		{args: wrapArgs(mustNotRaise(FrozenSetType.Call(NewRootFrame(), wrapArgs(newTestRange(100)), nil)), mustNotRaise(FrozenSetType.Call(NewRootFrame(), wrapArgs(newTestRange(100)), nil))), want: compareAllResultEq},
   107  		{args: wrapArgs(newTestFrozenSet(), NewSet()), want: newTestTuple(false, true, true, false, true, false).ToObject()},
   108  		{args: wrapArgs(newTestSet("foo", "bar"), newTestFrozenSet("foo", "bar")), want: newTestTuple(false, true, true, false, true, false).ToObject()},
   109  	}
   110  	for _, cas := range cases {
   111  		if err := runInvokeTestCase(compareAll, &cas); err != "" {
   112  			t.Error(err)
   113  		}
   114  	}
   115  }
   116  
   117  func TestSetIsSubset(t *testing.T) {
   118  	f := NewRootFrame()
   119  	for _, typ := range []*Type{SetType, FrozenSetType} {
   120  		cases := []invokeTestCase{
   121  			{args: wrapArgs(mustNotRaise(typ.Call(f, nil, nil)), newTestSet("foo")), want: True.ToObject()},
   122  			{args: wrapArgs(mustNotRaise(typ.Call(f, nil, nil)), newTestFrozenSet("foo")), want: True.ToObject()},
   123  			{args: wrapArgs(mustNotRaise(typ.Call(f, wrapArgs(newTestTuple(1, 2)), nil)), newTestSet(2, 3)), want: False.ToObject()},
   124  			{args: wrapArgs(mustNotRaise(typ.Call(f, wrapArgs(newTestTuple(1, 2)), nil)), newTestFrozenSet(2, 3)), want: False.ToObject()},
   125  			{args: wrapArgs(mustNotRaise(typ.Call(f, wrapArgs(newTestTuple("foo")), nil)), newTestTuple("bar")), want: False.ToObject()},
   126  			{args: wrapArgs(mustNotRaise(typ.Call(f, wrapArgs(newTestRange(42)), nil)), newTestRange(42)), want: True.ToObject()},
   127  			{args: wrapArgs(mustNotRaise(typ.Call(f, nil, nil)), 123), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")},
   128  			{args: wrapArgs(mustNotRaise(typ.Call(f, nil, nil)), "foo", "bar"), wantExc: mustCreateException(TypeErrorType, fmt.Sprintf("'issubset' of '%s' requires 2 arguments", typ.Name()))},
   129  		}
   130  		for _, cas := range cases {
   131  			if err := runInvokeMethodTestCase(typ, "issubset", &cas); err != "" {
   132  				t.Error(err)
   133  			}
   134  		}
   135  	}
   136  }
   137  
   138  func TestSetIsSuperset(t *testing.T) {
   139  	f := NewRootFrame()
   140  	for _, typ := range []*Type{SetType, FrozenSetType} {
   141  		cases := []invokeTestCase{
   142  			{args: wrapArgs(mustNotRaise(typ.Call(f, nil, nil)), newTestSet("foo")), want: False.ToObject()},
   143  			{args: wrapArgs(mustNotRaise(typ.Call(f, wrapArgs(newTestTuple(1, 2)), nil)), newTestSet(2, 3)), want: False.ToObject()},
   144  			{args: wrapArgs(mustNotRaise(typ.Call(f, wrapArgs(newTestTuple("foo")), nil)), newTestTuple("bar")), want: False.ToObject()},
   145  			{args: wrapArgs(mustNotRaise(typ.Call(f, wrapArgs(newTestRange(42)), nil)), newTestRange(42)), want: True.ToObject()},
   146  			{args: wrapArgs(mustNotRaise(typ.Call(f, nil, nil)), 123), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")},
   147  			{args: wrapArgs(mustNotRaise(typ.Call(f, nil, nil)), "foo", "bar"), wantExc: mustCreateException(TypeErrorType, fmt.Sprintf("'issuperset' of '%s' requires 2 arguments", typ.Name()))},
   148  		}
   149  		for _, cas := range cases {
   150  			if err := runInvokeMethodTestCase(typ, "issuperset", &cas); err != "" {
   151  				t.Error(err)
   152  			}
   153  		}
   154  	}
   155  }
   156  
   157  func TestSetIsTrue(t *testing.T) {
   158  	f := NewRootFrame()
   159  	for _, typ := range []*Type{SetType, FrozenSetType} {
   160  		cases := []invokeTestCase{
   161  			{args: wrapArgs(mustNotRaise(typ.Call(f, nil, nil))), want: False.ToObject()},
   162  			{args: wrapArgs(mustNotRaise(typ.Call(f, wrapArgs(newTestTuple("foo", None)), nil))), want: True.ToObject()},
   163  		}
   164  		for _, cas := range cases {
   165  			if err := runInvokeTestCase(wrapFuncForTest(IsTrue), &cas); err != "" {
   166  				t.Error(err)
   167  			}
   168  		}
   169  	}
   170  }
   171  
   172  func TestSetIter(t *testing.T) {
   173  	fun := wrapFuncForTest(func(f *Frame, s *Object) (*Tuple, *BaseException) {
   174  		var result *Tuple
   175  		raised := seqApply(f, s, func(elems []*Object, _ bool) *BaseException {
   176  			result = NewTuple(elems...)
   177  			return nil
   178  		})
   179  		if raised != nil {
   180  			return nil, raised
   181  		}
   182  		return result, nil
   183  	})
   184  	cases := []invokeTestCase{
   185  		{args: wrapArgs(NewSet()), want: NewTuple().ToObject()},
   186  		{args: wrapArgs(newTestSet(1, 2, 3)), want: newTestTuple(1, 2, 3).ToObject()},
   187  		{args: wrapArgs(newTestSet("foo", 3.14)), want: newTestTuple("foo", 3.14).ToObject()},
   188  		{args: wrapArgs(newTestFrozenSet()), want: NewTuple().ToObject()},
   189  		{args: wrapArgs(newTestFrozenSet(1, 2, 3)), want: newTestTuple(1, 2, 3).ToObject()},
   190  		{args: wrapArgs(newTestFrozenSet("foo", 3.14)), want: newTestTuple("foo", 3.14).ToObject()},
   191  	}
   192  	for _, cas := range cases {
   193  		if err := runInvokeTestCase(fun, &cas); err != "" {
   194  			t.Error(err)
   195  		}
   196  	}
   197  }
   198  
   199  func TestSetLen(t *testing.T) {
   200  	f := NewRootFrame()
   201  	for _, typ := range []*Type{SetType, FrozenSetType} {
   202  		cases := []invokeTestCase{
   203  			{args: wrapArgs(mustNotRaise(typ.Call(f, nil, nil))), want: NewInt(0).ToObject()},
   204  			{args: wrapArgs(mustNotRaise(typ.Call(f, wrapArgs(newTestTuple(1, 2, 3)), nil))), want: NewInt(3).ToObject()},
   205  		}
   206  		for _, cas := range cases {
   207  			if err := runInvokeMethodTestCase(typ, "__len__", &cas); err != "" {
   208  				t.Error(err)
   209  			}
   210  		}
   211  	}
   212  }
   213  
   214  func TestSetNewInit(t *testing.T) {
   215  	f := NewRootFrame()
   216  	for _, typ := range []*Type{SetType, FrozenSetType} {
   217  		cases := []invokeTestCase{
   218  			{want: NewSet().ToObject()},
   219  			{args: wrapArgs(newTestTuple("foo", "bar")), want: mustNotRaise(typ.Call(f, wrapArgs(newTestTuple("foo", "bar")), nil))},
   220  			{args: wrapArgs("abba"), want: mustNotRaise(typ.Call(f, wrapArgs(newTestTuple("a", "b")), nil))},
   221  			{args: wrapArgs(3.14), wantExc: mustCreateException(TypeErrorType, "'float' object is not iterable")},
   222  			{args: wrapArgs(NewTuple(), 1, 2, 3), wantExc: mustCreateException(TypeErrorType, fmt.Sprintf("%s expected at most 1 arguments, got 4", typ.Name()))},
   223  		}
   224  		for _, cas := range cases {
   225  			if err := runInvokeTestCase(typ.ToObject(), &cas); err != "" {
   226  				t.Error(err)
   227  			}
   228  		}
   229  	}
   230  }
   231  
   232  func TestSetRemove(t *testing.T) {
   233  	fun := wrapFuncForTest(func(f *Frame, s *Set, args ...*Object) (*Object, *BaseException) {
   234  		remove, raised := GetAttr(f, s.ToObject(), NewStr("remove"), nil)
   235  		if raised != nil {
   236  			return nil, raised
   237  		}
   238  		if _, raised := remove.Call(f, args, nil); raised != nil {
   239  			return nil, raised
   240  		}
   241  		return s.ToObject(), nil
   242  	})
   243  	cases := []invokeTestCase{
   244  		{args: wrapArgs(newTestSet(1, 2, 3), 2), want: newTestSet(1, 3).ToObject()},
   245  		{args: wrapArgs(newTestSet("foo", 3), "foo"), want: newTestSet(3).ToObject()},
   246  		{args: wrapArgs(NewSet(), "foo"), wantExc: mustCreateException(KeyErrorType, "foo")},
   247  		{args: wrapArgs(NewSet(), NewList()), wantExc: mustCreateException(TypeErrorType, "unhashable type: 'list'")},
   248  		{args: wrapArgs(NewSet(), "foo", "bar"), wantExc: mustCreateException(TypeErrorType, "'remove' of 'set' requires 2 arguments")},
   249  	}
   250  	for _, cas := range cases {
   251  		if err := runInvokeTestCase(fun, &cas); err != "" {
   252  			t.Error(err)
   253  		}
   254  	}
   255  }
   256  
   257  func TestSetStrRepr(t *testing.T) {
   258  	cases := []invokeTestCase{
   259  		{args: wrapArgs(NewSet()), want: NewStr("set([])").ToObject()},
   260  		{args: wrapArgs(newTestSet("foo")), want: NewStr("set(['foo'])").ToObject()},
   261  		{args: wrapArgs(newTestSet(TupleType, ExceptionType)), want: NewStr("set([<type 'tuple'>, <type 'Exception'>])").ToObject()},
   262  		{args: wrapArgs(newTestFrozenSet()), want: NewStr("frozenset([])").ToObject()},
   263  		{args: wrapArgs(newTestFrozenSet("foo")), want: NewStr("frozenset(['foo'])").ToObject()},
   264  		{args: wrapArgs(newTestFrozenSet(TupleType, ExceptionType)), want: NewStr("frozenset([<type 'tuple'>, <type 'Exception'>])").ToObject()},
   265  	}
   266  	for _, cas := range cases {
   267  		if err := runInvokeTestCase(wrapFuncForTest(ToStr), &cas); err != "" {
   268  			t.Error(err)
   269  		}
   270  		if err := runInvokeTestCase(wrapFuncForTest(Repr), &cas); err != "" {
   271  			t.Error(err)
   272  		}
   273  	}
   274  }
   275  
   276  func TestSetUpdate(t *testing.T) {
   277  	fun := wrapFuncForTest(func(f *Frame, s *Set, args ...*Object) (*Object, *BaseException) {
   278  		update, raised := GetAttr(f, s.ToObject(), NewStr("update"), nil)
   279  		if raised != nil {
   280  			return nil, raised
   281  		}
   282  		if _, raised := update.Call(f, args, nil); raised != nil {
   283  			return nil, raised
   284  		}
   285  		return s.ToObject(), nil
   286  	})
   287  	cases := []invokeTestCase{
   288  		{args: wrapArgs(NewSet(), "foo"), want: newTestSet("f", "o").ToObject()},
   289  		{args: wrapArgs(NewSet(), newTestDict(1, "1", 2, "2")), want: newTestSet(1, 2).ToObject()},
   290  		{args: wrapArgs(NewSet(), newTestTuple("foo", "bar", "bar")), want: newTestSet("foo", "bar").ToObject()},
   291  		{args: wrapArgs(NewSet(), newTestTuple(NewDict())), wantExc: mustCreateException(TypeErrorType, "unhashable type: 'dict'")},
   292  		{args: wrapArgs(NewSet(), 123), wantExc: mustCreateException(TypeErrorType, "'int' object is not iterable")},
   293  		{args: wrapArgs(NewSet(), "foo", "bar"), wantExc: mustCreateException(TypeErrorType, "'update' of 'set' requires 2 arguments")},
   294  	}
   295  	for _, cas := range cases {
   296  		if err := runInvokeTestCase(fun, &cas); err != "" {
   297  			t.Error(err)
   298  		}
   299  	}
   300  }
   301  
   302  func newTestSet(elems ...interface{}) *Set {
   303  	f := NewRootFrame()
   304  	wrappedElems, raised := seqWrapEach(f, elems...)
   305  	if raised != nil {
   306  		panic(raised)
   307  	}
   308  	s := NewSet()
   309  	for _, elem := range wrappedElems {
   310  		if _, raised := s.Add(f, elem); raised != nil {
   311  			panic(raised)
   312  		}
   313  	}
   314  	return s
   315  }
   316  
   317  func newTestFrozenSet(elems ...interface{}) *FrozenSet {
   318  	f := NewRootFrame()
   319  	wrappedElems, raised := seqWrapEach(f, elems...)
   320  	if raised != nil {
   321  		panic(raised)
   322  	}
   323  	d := NewDict()
   324  	for _, elem := range wrappedElems {
   325  		if raised := d.SetItem(f, elem, None); raised != nil {
   326  			panic(raised)
   327  		}
   328  	}
   329  	return &FrozenSet{Object{typ: FrozenSetType}, d}
   330  }