mirror of
https://github.com/gonum/gonum.git
synced 2025-10-07 16:11:03 +08:00
671 lines
13 KiB
Go
671 lines
13 KiB
Go
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package set
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
type node int64
|
|
|
|
func (n node) ID() int64 { return int64(n) }
|
|
|
|
// TestSame tests the assumption that pointer equality via unsafe conversion
|
|
// of a map[int]struct{} to uintptr is a valid test for perfect identity between
|
|
// set values. If any of the tests in TestSame fail, the package is broken and same
|
|
// must be reimplemented to conform to the runtime map implementation. The relevant
|
|
// code to look at (at least for gc) is the hmap type in runtime/map.go.
|
|
|
|
func TestSameInt64s(t *testing.T) {
|
|
var (
|
|
a = make(Int64s)
|
|
b = make(Int64s)
|
|
c = a
|
|
)
|
|
|
|
if int64sSame(a, b) {
|
|
t.Error("Independently created sets test as same")
|
|
}
|
|
if !int64sSame(a, c) {
|
|
t.Error("Set copy and original test as not same.")
|
|
}
|
|
a.Add(1)
|
|
if !int64sSame(a, c) {
|
|
t.Error("Set copy and original test as not same after addition.")
|
|
}
|
|
if !int64sSame(nil, nil) {
|
|
t.Error("nil sets test as not same.")
|
|
}
|
|
if int64sSame(b, nil) {
|
|
t.Error("nil and empty sets test as same.")
|
|
}
|
|
}
|
|
|
|
func TestAddInt64s(t *testing.T) {
|
|
s := make(Int64s)
|
|
if s.Count() != 0 {
|
|
t.Error("Set somehow contains new elements upon creation")
|
|
}
|
|
|
|
s.Add(1)
|
|
s.Add(3)
|
|
s.Add(5)
|
|
|
|
if s.Count() != 3 {
|
|
t.Error("Incorrect number of set elements after adding")
|
|
}
|
|
|
|
if !s.Has(1) || !s.Has(3) || !s.Has(5) {
|
|
t.Error("Set doesn't contain element that was added")
|
|
}
|
|
|
|
s.Add(1)
|
|
|
|
if s.Count() > 3 {
|
|
t.Error("Set double-adds element (element not unique)")
|
|
} else if s.Count() < 3 {
|
|
t.Error("Set double-add lowered len")
|
|
}
|
|
|
|
if !s.Has(1) {
|
|
t.Error("Set doesn't contain double-added element")
|
|
}
|
|
|
|
if !s.Has(3) || !s.Has(5) {
|
|
t.Error("Set removes element on double-add")
|
|
}
|
|
}
|
|
|
|
func TestRemoveInt64s(t *testing.T) {
|
|
s := make(Int64s)
|
|
|
|
s.Add(1)
|
|
s.Add(3)
|
|
s.Add(5)
|
|
|
|
s.Remove(1)
|
|
|
|
if s.Count() != 2 {
|
|
t.Error("Incorrect number of set elements after removing an element")
|
|
}
|
|
|
|
if s.Has(1) {
|
|
t.Error("Element present after removal")
|
|
}
|
|
|
|
if !s.Has(3) || !s.Has(5) {
|
|
t.Error("Set remove removed wrong element")
|
|
}
|
|
|
|
s.Remove(1)
|
|
|
|
if s.Count() != 2 || s.Has(1) {
|
|
t.Error("Double set remove does something strange")
|
|
}
|
|
|
|
s.Add(1)
|
|
|
|
if s.Count() != 3 || !s.Has(1) {
|
|
t.Error("Cannot add element after removal")
|
|
}
|
|
}
|
|
|
|
func TestSelfEqualInt64s(t *testing.T) {
|
|
s := make(Int64s)
|
|
|
|
if !Int64sEqual(s, s) {
|
|
t.Error("Set is not equal to itself")
|
|
}
|
|
|
|
s.Add(1)
|
|
|
|
if !Int64sEqual(s, s) {
|
|
t.Error("Set ceases self equality after adding element")
|
|
}
|
|
}
|
|
|
|
func TestEqualInt64s(t *testing.T) {
|
|
a := make(Int64s)
|
|
b := make(Int64s)
|
|
|
|
if !Int64sEqual(a, b) {
|
|
t.Error("Two different empty sets not equal")
|
|
}
|
|
|
|
a.Add(1)
|
|
if Int64sEqual(a, b) {
|
|
t.Error("Two different sets with different sizes equal")
|
|
}
|
|
|
|
b.Add(1)
|
|
if !Int64sEqual(a, b) {
|
|
t.Error("Two sets with same element not equal")
|
|
}
|
|
|
|
b.Remove(1)
|
|
b.Add(2)
|
|
if Int64sEqual(a, b) {
|
|
t.Error("Two different sets with different elements equal")
|
|
}
|
|
}
|
|
|
|
func TestSameInts(t *testing.T) {
|
|
var (
|
|
a = make(Ints)
|
|
b = make(Ints)
|
|
c = a
|
|
)
|
|
|
|
if intsSame(a, b) {
|
|
t.Error("Independently created sets test as same")
|
|
}
|
|
if !intsSame(a, c) {
|
|
t.Error("Set copy and original test as not same.")
|
|
}
|
|
a.Add(1)
|
|
if !intsSame(a, c) {
|
|
t.Error("Set copy and original test as not same after addition.")
|
|
}
|
|
if !intsSame(nil, nil) {
|
|
t.Error("nil sets test as not same.")
|
|
}
|
|
if intsSame(b, nil) {
|
|
t.Error("nil and empty sets test as same.")
|
|
}
|
|
}
|
|
|
|
func TestAddInts(t *testing.T) {
|
|
s := make(Ints)
|
|
if s.Count() != 0 {
|
|
t.Error("Set somehow contains new elements upon creation")
|
|
}
|
|
|
|
s.Add(1)
|
|
s.Add(3)
|
|
s.Add(5)
|
|
|
|
if s.Count() != 3 {
|
|
t.Error("Incorrect number of set elements after adding")
|
|
}
|
|
|
|
if !s.Has(1) || !s.Has(3) || !s.Has(5) {
|
|
t.Error("Set doesn't contain element that was added")
|
|
}
|
|
|
|
s.Add(1)
|
|
|
|
if s.Count() > 3 {
|
|
t.Error("Set double-adds element (element not unique)")
|
|
} else if s.Count() < 3 {
|
|
t.Error("Set double-add lowered len")
|
|
}
|
|
|
|
if !s.Has(1) {
|
|
t.Error("Set doesn't contain double-added element")
|
|
}
|
|
|
|
if !s.Has(3) || !s.Has(5) {
|
|
t.Error("Set removes element on double-add")
|
|
}
|
|
}
|
|
|
|
func TestRemoveInts(t *testing.T) {
|
|
s := make(Ints)
|
|
|
|
s.Add(1)
|
|
s.Add(3)
|
|
s.Add(5)
|
|
|
|
s.Remove(1)
|
|
|
|
if s.Count() != 2 {
|
|
t.Error("Incorrect number of set elements after removing an element")
|
|
}
|
|
|
|
if s.Has(1) {
|
|
t.Error("Element present after removal")
|
|
}
|
|
|
|
if !s.Has(3) || !s.Has(5) {
|
|
t.Error("Set remove removed wrong element")
|
|
}
|
|
|
|
s.Remove(1)
|
|
|
|
if s.Count() != 2 || s.Has(1) {
|
|
t.Error("Double set remove does something strange")
|
|
}
|
|
|
|
s.Add(1)
|
|
|
|
if s.Count() != 3 || !s.Has(1) {
|
|
t.Error("Cannot add element after removal")
|
|
}
|
|
}
|
|
|
|
func TestSelfEqualInts(t *testing.T) {
|
|
s := make(Ints)
|
|
|
|
if !IntsEqual(s, s) {
|
|
t.Error("Set is not equal to itself")
|
|
}
|
|
|
|
s.Add(1)
|
|
|
|
if !IntsEqual(s, s) {
|
|
t.Error("Set ceases self equality after adding element")
|
|
}
|
|
}
|
|
|
|
func TestEqualInts(t *testing.T) {
|
|
a := make(Ints)
|
|
b := make(Ints)
|
|
|
|
if !IntsEqual(a, b) {
|
|
t.Error("Two different empty sets not equal")
|
|
}
|
|
|
|
a.Add(1)
|
|
if IntsEqual(a, b) {
|
|
t.Error("Two different sets with different sizes equal")
|
|
}
|
|
|
|
b.Add(1)
|
|
if !IntsEqual(a, b) {
|
|
t.Error("Two sets with same element not equal")
|
|
}
|
|
|
|
b.Remove(1)
|
|
b.Add(2)
|
|
if IntsEqual(a, b) {
|
|
t.Error("Two different sets with different elements equal")
|
|
}
|
|
}
|
|
|
|
func TestSameNodes(t *testing.T) {
|
|
var (
|
|
a = NewNodes()
|
|
b = NewNodes()
|
|
c = a
|
|
)
|
|
|
|
if same(a, b) {
|
|
t.Error("Independently created sets test as same")
|
|
}
|
|
if !same(a, c) {
|
|
t.Error("Set copy and original test as not same.")
|
|
}
|
|
a.Add(node(1))
|
|
if !same(a, c) {
|
|
t.Error("Set copy and original test as not same after addition.")
|
|
}
|
|
if !same(nil, nil) {
|
|
t.Error("nil sets test as not same.")
|
|
}
|
|
if same(b, nil) {
|
|
t.Error("nil and empty sets test as same.")
|
|
}
|
|
}
|
|
|
|
func TestAddNodes(t *testing.T) {
|
|
s := NewNodes()
|
|
if s == nil {
|
|
t.Fatal("Set cannot be created successfully")
|
|
}
|
|
|
|
if s.Count() != 0 {
|
|
t.Error("Set somehow contains new elements upon creation")
|
|
}
|
|
|
|
s.Add(node(1))
|
|
s.Add(node(3))
|
|
s.Add(node(5))
|
|
|
|
if s.Count() != 3 {
|
|
t.Error("Incorrect number of set elements after adding")
|
|
}
|
|
|
|
if !s.Has(node(1)) || !s.Has(node(3)) || !s.Has(node(5)) {
|
|
t.Error("Set doesn't contain element that was added")
|
|
}
|
|
|
|
s.Add(node(1))
|
|
|
|
if s.Count() > 3 {
|
|
t.Error("Set double-adds element (element not unique)")
|
|
} else if s.Count() < 3 {
|
|
t.Error("Set double-add lowered len")
|
|
}
|
|
|
|
if !s.Has(node(1)) {
|
|
t.Error("Set doesn't contain double-added element")
|
|
}
|
|
|
|
if !s.Has(node(3)) || !s.Has(node(5)) {
|
|
t.Error("Set removes element on double-add")
|
|
}
|
|
|
|
for e, n := range s {
|
|
if e != n.ID() {
|
|
t.Errorf("Element ID did not match key: %d != %d", e, n.ID())
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRemoveNodes(t *testing.T) {
|
|
s := NewNodes()
|
|
|
|
s.Add(node(1))
|
|
s.Add(node(3))
|
|
s.Add(node(5))
|
|
|
|
s.Remove(node(1))
|
|
|
|
if s.Count() != 2 {
|
|
t.Error("Incorrect number of set elements after removing an element")
|
|
}
|
|
|
|
if s.Has(node(1)) {
|
|
t.Error("Element present after removal")
|
|
}
|
|
|
|
if !s.Has(node(3)) || !s.Has(node(5)) {
|
|
t.Error("Set remove removed wrong element")
|
|
}
|
|
|
|
s.Remove(node(1))
|
|
|
|
if s.Count() != 2 || s.Has(node(1)) {
|
|
t.Error("Double set remove does something strange")
|
|
}
|
|
|
|
s.Add(node(1))
|
|
|
|
if s.Count() != 3 || !s.Has(node(1)) {
|
|
t.Error("Cannot add element after removal")
|
|
}
|
|
}
|
|
|
|
func TestSelfEqualNodes(t *testing.T) {
|
|
s := NewNodes()
|
|
|
|
if !Equal(s, s) {
|
|
t.Error("Set is not equal to itself")
|
|
}
|
|
|
|
s.Add(node(1))
|
|
|
|
if !Equal(s, s) {
|
|
t.Error("Set ceases self equality after adding element")
|
|
}
|
|
}
|
|
|
|
func TestEqualNodes(t *testing.T) {
|
|
a := NewNodes()
|
|
b := NewNodes()
|
|
|
|
if !Equal(a, b) {
|
|
t.Error("Two different empty sets not equal")
|
|
}
|
|
|
|
a.Add(node(1))
|
|
if Equal(a, b) {
|
|
t.Error("Two different sets with different sizes equal")
|
|
}
|
|
|
|
b.Add(node(1))
|
|
if !Equal(a, b) {
|
|
t.Error("Two sets with same element not equal")
|
|
}
|
|
|
|
b.Remove(node(1))
|
|
b.Add(node(2))
|
|
if Equal(a, b) {
|
|
t.Error("Two different sets with different elements equal")
|
|
}
|
|
}
|
|
|
|
func TestCopyNodes(t *testing.T) {
|
|
a := NewNodes()
|
|
|
|
a.Add(node(1))
|
|
a.Add(node(2))
|
|
a.Add(node(3))
|
|
|
|
b := CloneNodes(a)
|
|
|
|
if !Equal(a, b) {
|
|
t.Fatalf("Two sets not equal after copy: %v != %v", a, b)
|
|
}
|
|
|
|
b.Remove(node(1))
|
|
|
|
if Equal(a, b) {
|
|
t.Errorf("Mutating one set mutated another after copy: %v == %v", a, b)
|
|
}
|
|
}
|
|
|
|
func TestUnionSameNodes(t *testing.T) {
|
|
a := NewNodes()
|
|
b := NewNodes()
|
|
|
|
a.Add(node(1))
|
|
a.Add(node(2))
|
|
|
|
b.Add(node(1))
|
|
b.Add(node(2))
|
|
|
|
c := UnionOfNodes(a, b)
|
|
|
|
if c.Count() != 2 {
|
|
t.Error("Union of same sets yields set with wrong len")
|
|
}
|
|
|
|
if !c.Has(node(1)) || !c.Has(node(2)) {
|
|
t.Error("Union of same sets yields wrong elements")
|
|
}
|
|
|
|
for i, s := range []Nodes{a, b, c} {
|
|
for e, n := range s {
|
|
if e != n.ID() {
|
|
t.Errorf("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestUnionDiffNodes(t *testing.T) {
|
|
a := NewNodes()
|
|
b := NewNodes()
|
|
|
|
a.Add(node(1))
|
|
a.Add(node(2))
|
|
|
|
b.Add(node(3))
|
|
|
|
c := UnionOfNodes(a, b)
|
|
|
|
if c.Count() != 3 {
|
|
t.Error("Union of different sets yields set with wrong len")
|
|
}
|
|
|
|
if !c.Has(node(1)) || !c.Has(node(2)) || !c.Has(node(3)) {
|
|
t.Error("Union of different sets yields set with wrong elements")
|
|
}
|
|
|
|
if a.Has(node(3)) || !a.Has(node(2)) || !a.Has(node(1)) || a.Count() != 2 {
|
|
t.Error("Union of sets mutates non-destination set (argument 1)")
|
|
}
|
|
|
|
if !b.Has(node(3)) || b.Has(node(1)) || b.Has(node(2)) || b.Count() != 1 {
|
|
t.Error("Union of sets mutates non-destination set (argument 2)")
|
|
}
|
|
|
|
for i, s := range []Nodes{a, b, c} {
|
|
for e, n := range s {
|
|
if e != n.ID() {
|
|
t.Errorf("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID())
|
|
}
|
|
}
|
|
}
|
|
|
|
c = UnionOfNodes(a, a)
|
|
if !reflect.DeepEqual(c, a) {
|
|
t.Errorf("Union of equal sets not equal to sets: %v != %v", c, a)
|
|
}
|
|
}
|
|
|
|
func TestUnionOverlappingNodes(t *testing.T) {
|
|
a := NewNodes()
|
|
b := NewNodes()
|
|
|
|
a.Add(node(1))
|
|
a.Add(node(2))
|
|
|
|
b.Add(node(2))
|
|
b.Add(node(3))
|
|
|
|
c := UnionOfNodes(a, b)
|
|
|
|
if c.Count() != 3 {
|
|
t.Error("Union of overlapping sets yields set with wrong len")
|
|
}
|
|
|
|
if !c.Has(node(1)) || !c.Has(node(2)) || !c.Has(node(3)) {
|
|
t.Error("Union of overlapping sets yields set with wrong elements")
|
|
}
|
|
|
|
if a.Has(node(3)) || !a.Has(node(2)) || !a.Has(node(1)) || a.Count() != 2 {
|
|
t.Error("Union of sets mutates non-destination set (argument 1)")
|
|
}
|
|
|
|
if !b.Has(node(3)) || b.Has(node(1)) || !b.Has(node(2)) || b.Count() != 2 {
|
|
t.Error("Union of sets mutates non-destination set (argument 2)")
|
|
}
|
|
|
|
for i, s := range []Nodes{a, b, c} {
|
|
for e, n := range s {
|
|
if e != n.ID() {
|
|
t.Errorf("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID())
|
|
}
|
|
}
|
|
}
|
|
|
|
c = IntersectionOfNodes(a, a)
|
|
if !reflect.DeepEqual(c, a) {
|
|
t.Errorf("Intersection of equal sets not equal to sets: %v != %v", c, a)
|
|
}
|
|
}
|
|
|
|
func TestIntersectSameNodes(t *testing.T) {
|
|
a := NewNodes()
|
|
b := NewNodes()
|
|
|
|
a.Add(node(2))
|
|
a.Add(node(3))
|
|
|
|
b.Add(node(2))
|
|
b.Add(node(3))
|
|
|
|
c := IntersectionOfNodes(a, b)
|
|
|
|
if card := c.Count(); card != 2 {
|
|
t.Errorf("Intersection of identical sets yields set of wrong len %d", card)
|
|
}
|
|
|
|
if !c.Has(node(2)) || !c.Has(node(3)) {
|
|
t.Error("Intersection of identical sets yields set of wrong elements")
|
|
}
|
|
|
|
for i, s := range []Nodes{a, b, c} {
|
|
for e, n := range s {
|
|
if e != n.ID() {
|
|
t.Errorf("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestIntersectDiffNodes(t *testing.T) {
|
|
a := NewNodes()
|
|
b := NewNodes()
|
|
|
|
a.Add(node(2))
|
|
a.Add(node(3))
|
|
|
|
b.Add(node(1))
|
|
b.Add(node(4))
|
|
|
|
c := IntersectionOfNodes(a, b)
|
|
|
|
if card := c.Count(); card != 0 {
|
|
t.Errorf("Intersection of different yields non-empty set %d", card)
|
|
}
|
|
|
|
if !a.Has(node(2)) || !a.Has(node(3)) || a.Has(node(1)) || a.Has(node(4)) || a.Count() != 2 {
|
|
t.Error("Intersection of sets mutates non-destination set (argument 1)")
|
|
}
|
|
|
|
if b.Has(node(2)) || b.Has(node(3)) || !b.Has(node(1)) || !b.Has(node(4)) || b.Count() != 2 {
|
|
t.Error("Intersection of sets mutates non-destination set (argument 1)")
|
|
}
|
|
|
|
for i, s := range []Nodes{a, b, c} {
|
|
for e, n := range s {
|
|
if e != n.ID() {
|
|
t.Errorf("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestIntersectOverlappingNodes(t *testing.T) {
|
|
a := NewNodes()
|
|
b := NewNodes()
|
|
|
|
a.Add(node(2))
|
|
a.Add(node(3))
|
|
|
|
b.Add(node(3))
|
|
b.Add(node(4))
|
|
|
|
c := IntersectionOfNodes(a, b)
|
|
|
|
if card := c.Count(); card != 1 {
|
|
t.Errorf("Intersection of overlapping sets yields set of incorrect len %d", card)
|
|
}
|
|
|
|
if !c.Has(node(3)) {
|
|
t.Errorf("Intersection of overlapping sets yields set with wrong element")
|
|
}
|
|
|
|
if !a.Has(node(2)) || !a.Has(node(3)) || a.Has(node(4)) || a.Count() != 2 {
|
|
t.Error("Intersection of sets mutates non-destination set (argument 1)")
|
|
}
|
|
|
|
if b.Has(node(2)) || !b.Has(node(3)) || !b.Has(node(4)) || b.Count() != 2 {
|
|
t.Error("Intersection of sets mutates non-destination set (argument 1)")
|
|
}
|
|
|
|
for i, s := range []Nodes{a, b, c} {
|
|
for e, n := range s {
|
|
if e != n.ID() {
|
|
t.Errorf("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID())
|
|
}
|
|
}
|
|
}
|
|
|
|
c = IntersectionOfNodes(c, a)
|
|
want := Nodes{3: node(3)}
|
|
if !reflect.DeepEqual(c, want) {
|
|
t.Errorf("Intersection of sets with dst equal to a not equal: %v != %v", c, want)
|
|
}
|
|
c = IntersectionOfNodes(a, c)
|
|
if !reflect.DeepEqual(c, want) {
|
|
t.Errorf("Intersection of sets with dst equal to a not equal: %v != %v", c, want)
|
|
}
|
|
}
|