github.com/google/grumpy@v0.0.0-20171122020858-3ec87959189c/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 }