graph/encoding/dot: don't propagate edge-setting panics when unmarshaling DOT

This commit is contained in:
Dan Kortschak
2020-11-20 09:10:08 +10:30
parent cb7e73b504
commit 4cb41c693f
2 changed files with 67 additions and 0 deletions

View File

@@ -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)

View File

@@ -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
}