mirror of
https://github.com/caddyserver/caddy.git
synced 2026-09-15 07:11:10 -04:00
caddyfile: fix importGraph self-loop and stale-edge bugs (#7971)
- willCycle now reports a cycle when from == to, so addEdge rejects self-loops (a self-importing file was previously accepted). - removeNode now drops the removed node's outgoing edges and any incoming edges pointing at it, keeping the adjacency map consistent. Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com>
This commit is contained in:
1 parent
af29f9ea91
commit
2cb7ebca45
2 files changed
+52
No files matched your search
@@ -44,6 +44,10 @@ func (i *importGraph) addNodes(names []string) {
|
||||
|
||||
func (i *importGraph) removeNode(name string) {
|
||||
delete(i.nodes, name)
|
||||
delete(i.edges, name)
|
||||
for k, targets := range i.edges {
|
||||
i.edges[k] = slices.DeleteFunc(targets, func(t string) bool { return t == name })
|
||||
}
|
||||
}
|
||||
|
||||
func (i *importGraph) removeNodes(names []string) {
|
||||
@@ -96,6 +100,9 @@ func (i *importGraph) areConnected(from, to string) bool {
|
||||
}
|
||||
|
||||
func (i *importGraph) willCycle(from, to string) bool {
|
||||
if from == to {
|
||||
return true
|
||||
}
|
||||
collector := make(map[string]bool)
|
||||
|
||||
var visit func(string)
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2015 Matthew Holt and The Caddy Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package caddyfile
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestImportGraphSelfLoop(t *testing.T) {
|
||||
g := &importGraph{}
|
||||
g.addNode("a")
|
||||
|
||||
if err := g.addEdge("a", "a"); err == nil {
|
||||
t.Error("expected error for self-loop cycle a -> a")
|
||||
}
|
||||
}
|
||||
|
||||
func TestImportGraphRemoveNodeCleansEdges(t *testing.T) {
|
||||
g := &importGraph{}
|
||||
g.addNodes([]string{"a", "b", "c"})
|
||||
_ = g.addEdge("a", "b")
|
||||
_ = g.addEdge("b", "c")
|
||||
|
||||
g.removeNode("b")
|
||||
|
||||
if g.exists("b") {
|
||||
t.Error("node 'b' should not exist after removeNode")
|
||||
}
|
||||
if targets, ok := g.edges["b"]; ok && len(targets) > 0 {
|
||||
t.Errorf("outgoing edges from removed node 'b' should be cleared, got %v", targets)
|
||||
}
|
||||
if g.areConnected("a", "b") {
|
||||
t.Error("incoming edge 'a' -> 'b' should be removed when 'b' is removed")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user