86 lines
2.6 KiB
Go
Executable File
86 lines
2.6 KiB
Go
Executable File
package dag
|
|
|
|
import "testing"
|
|
|
|
// TestCircularDependency reproduces the original "A -> B -> C -> A" loop and
|
|
// ensures DetectCycles rejects the offending edge while keeping the Graph
|
|
// in a valid state (edge is rolled back).
|
|
func TestCircularDependency(t *testing.T) {
|
|
g := NewGraph()
|
|
if err := g.AddDependency("gcc", "glibc", BuildDep, nil); err != nil {
|
|
t.Fatalf("first edge should succeed: %v", err)
|
|
}
|
|
if err := g.AddDependency("glibc", "linux-headers", BuildDep, nil); err != nil {
|
|
t.Fatalf("second edge should succeed: %v", err)
|
|
}
|
|
// Closing the loop must fail.
|
|
if err := g.AddDependency("linux-headers", "gcc", BuildDep, nil); err == nil {
|
|
t.Fatalf("expected cycle error, got nil")
|
|
} else {
|
|
t.Logf("✓ correctly caught loop: %v", err)
|
|
}
|
|
// Graph must still be intact (rolled back).
|
|
if n := g.Nodes["linux-headers"]; n != nil && len(n.Edges) != 0 {
|
|
t.Fatalf("linux-headers should have no edges after rollback, got %d", len(n.Edges))
|
|
}
|
|
}
|
|
|
|
func TestTopologicalSort(t *testing.T) {
|
|
g := NewGraph()
|
|
_ = g.AddDependency("wget", "openssl", RuntimeDep, nil)
|
|
_ = g.AddDependency("wget", "glibc", RuntimeDep, nil)
|
|
_ = g.AddDependency("openssl", "glibc", RuntimeDep, nil)
|
|
|
|
order, err := g.TopologicalSort()
|
|
if err != nil {
|
|
t.Fatalf("topo sort: %v", err)
|
|
}
|
|
pos := make(map[string]int)
|
|
for i, n := range order {
|
|
pos[n.Name] = i
|
|
}
|
|
if pos["glibc"] >= pos["openssl"] {
|
|
t.Fatalf("glibc must come before openssl")
|
|
}
|
|
if pos["glibc"] >= pos["wget"] {
|
|
t.Fatalf("glibc must come before wget")
|
|
}
|
|
if pos["openssl"] >= pos["wget"] {
|
|
t.Fatalf("openssl must come before wget")
|
|
}
|
|
}
|
|
|
|
func TestPruneSkipsOptional(t *testing.T) {
|
|
g := NewGraph()
|
|
_ = g.AddDependency("app", "libcore", RuntimeDep, nil)
|
|
_ = g.AddDependency("app", "libx11", OptionalDep, nil)
|
|
_ = g.AddDependency("libx11", "libxext", RuntimeDep, nil)
|
|
|
|
g.Prune("app", false)
|
|
if !g.Nodes["libcore"].IsRequired {
|
|
t.Fatalf("libcore must be required")
|
|
}
|
|
if g.Nodes["libx11"].IsRequired {
|
|
t.Fatalf("libx11 (optional, not enabled) must be pruned")
|
|
}
|
|
if g.Nodes["libxext"].IsRequired {
|
|
t.Fatalf("libxext must be pruned along with libx11")
|
|
}
|
|
}
|
|
|
|
func TestSolverTriggersReForge(t *testing.T) {
|
|
g := NewGraph()
|
|
_ = g.AddDependency("wget", "openssl", RuntimeDep, []string{"ssl3"})
|
|
// Pretend the existing openssl Essence does NOT have ssl3 enabled.
|
|
s := &Solver{Lookup: func(spell, feature string) (bool, error) {
|
|
return false, nil
|
|
}}
|
|
reforges, err := s.Solve("wget", g)
|
|
if err != nil {
|
|
t.Fatalf("solve: %v", err)
|
|
}
|
|
if len(reforges) == 0 {
|
|
t.Fatalf("expected a re-forge recommendation for openssl+ssl3")
|
|
}
|
|
}
|