mirror of
https://github.com/gonum/gonum.git
synced 2025-10-06 15:47:01 +08:00
graph/encoding/dot: don't propagate edge-setting panics when unmarshaling DOT
This commit is contained in:
@@ -275,6 +275,16 @@ func applyPortsToEdge(from ast.Vertex, to *ast.Edge, edge basicEdge) {
|
|||||||
func (gen *simpleGraph) addEdgeStmt(dst encoding.Builder, stmt *ast.EdgeStmt) {
|
func (gen *simpleGraph) addEdgeStmt(dst encoding.Builder, stmt *ast.EdgeStmt) {
|
||||||
fs := gen.addVertex(dst, stmt.From)
|
fs := gen.addVertex(dst, stmt.From)
|
||||||
ts := gen.addEdge(dst, stmt.To, stmt.Attrs)
|
ts := gen.addEdge(dst, stmt.To, stmt.Attrs)
|
||||||
|
defer func() {
|
||||||
|
switch e := recover().(type) {
|
||||||
|
case nil:
|
||||||
|
// Do nothing.
|
||||||
|
case error:
|
||||||
|
panic(e)
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("panic setting edge: %v", e))
|
||||||
|
}
|
||||||
|
}()
|
||||||
for _, f := range fs {
|
for _, f := range fs {
|
||||||
for _, t := range ts {
|
for _, t := range ts {
|
||||||
edge := dst.NewEdge(f, t)
|
edge := dst.NewEdge(f, t)
|
||||||
|
@@ -644,3 +644,60 @@ func (a *attributes) SetAttribute(attr encoding.Attribute) error {
|
|||||||
*a = append(*a, attr)
|
*a = append(*a, attr)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const undirectedSelfLoopGraph = `graph {
|
||||||
|
// Node definitions.
|
||||||
|
0;
|
||||||
|
1;
|
||||||
|
|
||||||
|
// Edge definitions.
|
||||||
|
0 -- 0;
|
||||||
|
1 -- 1;
|
||||||
|
}`
|
||||||
|
|
||||||
|
const directedSelfLoopGraph = `digraph {
|
||||||
|
// Node definitions.
|
||||||
|
0;
|
||||||
|
1;
|
||||||
|
|
||||||
|
// Edge definitions.
|
||||||
|
0 -> 0;
|
||||||
|
1 -> 1;
|
||||||
|
}`
|
||||||
|
|
||||||
|
func TestSelfLoopSimple(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
dst func() encoding.Builder
|
||||||
|
src string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
dst: func() encoding.Builder { return simple.NewUndirectedGraph() },
|
||||||
|
src: undirectedSelfLoopGraph,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dst: func() encoding.Builder { return simple.NewDirectedGraph() },
|
||||||
|
src: directedSelfLoopGraph,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
dst := test.dst()
|
||||||
|
message, panicked := panics(func() {
|
||||||
|
err := Unmarshal([]byte(test.src), dst)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("expected error for self loop addition to %T", dst)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if panicked {
|
||||||
|
t.Errorf("unexpected panic for self loop addition to %T: %s", dst, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func panics(fn func()) (message string, ok bool) {
|
||||||
|
defer func() {
|
||||||
|
r := recover()
|
||||||
|
message = fmt.Sprint(r)
|
||||||
|
ok = r != nil
|
||||||
|
}()
|
||||||
|
fn()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user