a rusty set datastructure for go

set: add proprty based tests

very cool that this is builtin to go!

Signed-off-by: oppiliappan <me@oppi.li>

oppi.li 714a80a6 4710e037

verified
Changed files
+191
+31
gen.go
··· 1 + package set 2 + 3 + import ( 4 + "math/rand" 5 + "reflect" 6 + "testing/quick" 7 + ) 8 + 9 + func (_ Set[T]) Generate(rand *rand.Rand, size int) reflect.Value { 10 + s := New[T]() 11 + 12 + var zero T 13 + itemType := reflect.TypeOf(zero) 14 + 15 + for { 16 + if s.Len() >= size { 17 + break 18 + } 19 + 20 + item, ok := quick.Value(itemType, rand) 21 + if !ok { 22 + continue 23 + } 24 + 25 + if val, ok := item.Interface().(T); ok { 26 + s.Insert(val) 27 + } 28 + } 29 + 30 + return reflect.ValueOf(s) 31 + }
+160
set_test.go
··· 3 3 import ( 4 4 "slices" 5 5 "testing" 6 + "testing/quick" 6 7 ) 7 8 8 9 func TestNew(t *testing.T) { ··· 238 239 t.Error("Difference set should contain 1") 239 240 } 240 241 } 242 + 243 + func TestPropertyInsertIdempotent(t *testing.T) { 244 + f := func(s Set[int], item int) bool { 245 + clone := s.Clone() 246 + 247 + clone.Insert(item) 248 + firstLen := clone.Len() 249 + 250 + clone.Insert(item) 251 + secondLen := clone.Len() 252 + 253 + return firstLen == secondLen 254 + } 255 + 256 + if err := quick.Check(f, nil); err != nil { 257 + t.Error(err) 258 + } 259 + } 260 + 261 + func TestPropertyUnionCommutative(t *testing.T) { 262 + f := func(s1 Set[int], s2 Set[int]) bool { 263 + union1 := Collect(s1.Union(s2)) 264 + union2 := Collect(s2.Union(s1)) 265 + return union1.Equal(union2) 266 + } 267 + 268 + if err := quick.Check(f, nil); err != nil { 269 + t.Error(err) 270 + } 271 + } 272 + 273 + func TestPropertyIntersectionCommutative(t *testing.T) { 274 + f := func(s1 Set[int], s2 Set[int]) bool { 275 + inter1 := Collect(s1.Intersection(s2)) 276 + inter2 := Collect(s2.Intersection(s1)) 277 + return inter1.Equal(inter2) 278 + } 279 + 280 + if err := quick.Check(f, nil); err != nil { 281 + t.Error(err) 282 + } 283 + } 284 + 285 + func TestPropertyCloneEquals(t *testing.T) { 286 + f := func(s Set[int]) bool { 287 + clone := s.Clone() 288 + return s.Equal(clone) 289 + } 290 + 291 + if err := quick.Check(f, nil); err != nil { 292 + t.Error(err) 293 + } 294 + } 295 + 296 + func TestPropertyIntersectionIsSubset(t *testing.T) { 297 + f := func(s1 Set[int], s2 Set[int]) bool { 298 + inter := Collect(s1.Intersection(s2)) 299 + return inter.IsSubset(s1) && inter.IsSubset(s2) 300 + } 301 + 302 + if err := quick.Check(f, nil); err != nil { 303 + t.Error(err) 304 + } 305 + } 306 + 307 + func TestPropertyUnionIsSuperset(t *testing.T) { 308 + f := func(s1 Set[int], s2 Set[int]) bool { 309 + union := Collect(s1.Union(s2)) 310 + return union.IsSuperset(s1) && union.IsSuperset(s2) 311 + } 312 + 313 + if err := quick.Check(f, nil); err != nil { 314 + t.Error(err) 315 + } 316 + } 317 + 318 + func TestPropertyDifferenceDisjoint(t *testing.T) { 319 + f := func(s1 Set[int], s2 Set[int]) bool { 320 + diff := Collect(s1.Difference(s2)) 321 + return diff.IsDisjoint(s2) 322 + } 323 + 324 + if err := quick.Check(f, nil); err != nil { 325 + t.Error(err) 326 + } 327 + } 328 + 329 + func TestPropertySymmetricDifferenceCommutative(t *testing.T) { 330 + f := func(s1 Set[int], s2 Set[int]) bool { 331 + symDiff1 := Collect(s1.SymmetricDifference(s2)) 332 + symDiff2 := Collect(s2.SymmetricDifference(s1)) 333 + return symDiff1.Equal(symDiff2) 334 + } 335 + 336 + if err := quick.Check(f, nil); err != nil { 337 + t.Error(err) 338 + } 339 + } 340 + 341 + func TestPropertyRemoveWorks(t *testing.T) { 342 + f := func(s Set[int], item int) bool { 343 + clone := s.Clone() 344 + clone.Insert(item) 345 + clone.Remove(item) 346 + return !clone.Contains(item) 347 + } 348 + 349 + if err := quick.Check(f, nil); err != nil { 350 + t.Error(err) 351 + } 352 + } 353 + 354 + func TestPropertyClearEmpty(t *testing.T) { 355 + f := func(s Set[int]) bool { 356 + s.Clear() 357 + return s.IsEmpty() && s.Len() == 0 358 + } 359 + 360 + if err := quick.Check(f, nil); err != nil { 361 + t.Error(err) 362 + } 363 + } 364 + 365 + func TestPropertyIsSubsetReflexive(t *testing.T) { 366 + f := func(s Set[int]) bool { 367 + return s.IsSubset(s) 368 + } 369 + 370 + if err := quick.Check(f, nil); err != nil { 371 + t.Error(err) 372 + } 373 + } 374 + 375 + func TestPropertyDeMorganUnion(t *testing.T) { 376 + f := func(s1 Set[int], s2 Set[int], universe Set[int]) bool { 377 + // create a universe that contains both sets 378 + u := universe.Clone() 379 + for item := range s1.All() { 380 + u.Insert(item) 381 + } 382 + for item := range s2.All() { 383 + u.Insert(item) 384 + } 385 + 386 + // (A u B)' = A' n B' 387 + union := Collect(s1.Union(s2)) 388 + complementUnion := Collect(u.Difference(union)) 389 + 390 + complementS1 := Collect(u.Difference(s1)) 391 + complementS2 := Collect(u.Difference(s2)) 392 + intersectionComplements := Collect(complementS1.Intersection(complementS2)) 393 + 394 + return complementUnion.Equal(intersectionComplements) 395 + } 396 + 397 + if err := quick.Check(f, nil); err != nil { 398 + t.Error(err) 399 + } 400 + }