126 lines
3.3 KiB
Go
126 lines
3.3 KiB
Go
package tests
|
|
|
|
import (
|
|
"slices"
|
|
"testing"
|
|
|
|
"datastructures/graphs"
|
|
)
|
|
|
|
func TestNewDirectedGraphIsEmpty(t *testing.T) {
|
|
graph := graphs.NewDirectedGraph[int]()
|
|
|
|
if graph.Order() != 0 {
|
|
t.Errorf("new graph Order = %d, want 0", graph.Order())
|
|
}
|
|
if graph.Size() != 0 {
|
|
t.Errorf("new graph Size = %d, want 0", graph.Size())
|
|
}
|
|
}
|
|
|
|
func TestDirectedAddVertexIsOneWay(t *testing.T) {
|
|
graph := graphs.NewDirectedGraph[string]()
|
|
graph.AddVertex("a", "b")
|
|
|
|
if graph.Order() != 2 {
|
|
t.Errorf("Order = %d, want 2", graph.Order())
|
|
}
|
|
if graph.Size() != 1 {
|
|
t.Errorf("Size = %d, want 1", graph.Size())
|
|
}
|
|
|
|
adjacency := graph.Display()
|
|
if !slices.Contains(adjacency["a"], "b") {
|
|
t.Errorf("expected b in a's out-list, got %v", adjacency["a"])
|
|
}
|
|
// directed: the edge must NOT appear in reverse.
|
|
if slices.Contains(adjacency["b"], "a") {
|
|
t.Errorf("directed edge should not point back, got b: %v", adjacency["b"])
|
|
}
|
|
}
|
|
|
|
func TestDirectedSizeCountsEachEdgeOnce(t *testing.T) {
|
|
graph := graphs.NewDirectedGraph[string]()
|
|
graph.AddVertex("a", "b")
|
|
graph.AddVertex("b", "a")
|
|
|
|
// two distinct directed edges: a->b and b->a
|
|
if graph.Size() != 2 {
|
|
t.Errorf("Size = %d, want 2 (a->b and b->a are distinct)", graph.Size())
|
|
}
|
|
}
|
|
|
|
func TestDirectedAddVertexIsIdempotent(t *testing.T) {
|
|
graph := graphs.NewDirectedGraph[string]()
|
|
graph.AddVertex("a", "b")
|
|
graph.AddVertex("a", "b")
|
|
|
|
if len(graph.Display()["a"]) != 1 {
|
|
t.Errorf("expected no duplicate edge, got %v", graph.Display()["a"])
|
|
}
|
|
if graph.Size() != 1 {
|
|
t.Errorf("Size = %d, want 1", graph.Size())
|
|
}
|
|
}
|
|
|
|
// Regression: a vertex that is already the target of an edge must still be
|
|
// able to have its own outgoing edges (the old check2 loop broke this).
|
|
func TestDirectedTargetCanHaveOutgoingEdges(t *testing.T) {
|
|
graph := graphs.NewDirectedGraph[string]()
|
|
graph.AddVertex("c", "a") // a is now a target
|
|
graph.AddVertex("a", "b") // a must still be allowed an out-edge
|
|
|
|
if !slices.Contains(graph.Display()["a"], "b") {
|
|
t.Errorf("expected a->b even though a is a target, got a: %v", graph.Display()["a"])
|
|
}
|
|
if graph.Size() != 2 {
|
|
t.Errorf("Size = %d, want 2", graph.Size())
|
|
}
|
|
}
|
|
|
|
func TestDirectedMultipleOutEdges(t *testing.T) {
|
|
graph := graphs.NewDirectedGraph[int]()
|
|
graph.AddVertex(1, 2)
|
|
graph.AddVertex(1, 3)
|
|
graph.AddVertex(1, 4)
|
|
|
|
if graph.Order() != 4 {
|
|
t.Errorf("Order = %d, want 4", graph.Order())
|
|
}
|
|
if graph.Size() != 3 {
|
|
t.Errorf("Size = %d, want 3", graph.Size())
|
|
}
|
|
if len(graph.Display()[1]) != 3 {
|
|
t.Errorf("expected vertex 1 out-degree 3, got %v", graph.Display()[1])
|
|
}
|
|
}
|
|
|
|
func TestDirectedSelfLoopRejected(t *testing.T) {
|
|
graph := graphs.NewDirectedGraph[int]()
|
|
graph.AddVertex(1, 1)
|
|
|
|
if graph.Size() != 0 {
|
|
t.Errorf("self-loop should add no edge, Size = %d", graph.Size())
|
|
}
|
|
if slices.Contains(graph.Display()[1], 1) {
|
|
t.Errorf("vertex 1 should not point to itself, got %v", graph.Display()[1])
|
|
}
|
|
}
|
|
|
|
func TestDirectedAddIsolatedVertex(t *testing.T) {
|
|
graph := graphs.NewDirectedGraph[string]()
|
|
|
|
if !graph.AddIsolatedVertex("solo") {
|
|
t.Error("AddIsolatedVertex on new vertex = false, want true")
|
|
}
|
|
if graph.AddIsolatedVertex("solo") {
|
|
t.Error("AddIsolatedVertex on existing vertex = true, want false")
|
|
}
|
|
if graph.Order() != 1 {
|
|
t.Errorf("Order = %d, want 1", graph.Order())
|
|
}
|
|
if graph.Size() != 0 {
|
|
t.Errorf("isolated vertex should add no edges, Size = %d", graph.Size())
|
|
}
|
|
}
|