github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/graph/formats/dot/internal/parser/parser_test.go (about) 1 // This file is dual licensed under CC0 and The Gonum License. 2 // 3 // Copyright ©2017 The Gonum Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 // 7 // Copyright ©2017 Robin Eklind. 8 // This file is made available under a Creative Commons CC0 1.0 9 // Universal Public Domain Dedication. 10 11 package parser_test 12 13 import ( 14 "archive/zip" 15 "bytes" 16 "io/ioutil" 17 "os" 18 "testing" 19 20 "github.com/jingcheng-WU/gonum/graph/formats/dot" 21 ) 22 23 func TestParseFile(t *testing.T) { 24 golden := []struct { 25 in string 26 out string 27 }{ 28 {in: "../testdata/empty.dot"}, 29 {in: "../testdata/graph.dot"}, 30 {in: "../testdata/digraph.dot"}, 31 {in: "../testdata/strict.dot"}, 32 {in: "../testdata/multi.dot"}, 33 {in: "../testdata/named_graph.dot"}, 34 {in: "../testdata/node_stmt.dot"}, 35 {in: "../testdata/edge_stmt.dot"}, 36 {in: "../testdata/attr_stmt.dot"}, 37 {in: "../testdata/attr.dot"}, 38 { 39 in: "../testdata/subgraph.dot", 40 out: "../testdata/subgraph.golden", 41 }, 42 { 43 in: "../testdata/semi.dot", 44 out: "../testdata/semi.golden", 45 }, 46 { 47 in: "../testdata/empty_attr.dot", 48 out: "../testdata/empty_attr.golden", 49 }, 50 { 51 in: "../testdata/attr_lists.dot", 52 out: "../testdata/attr_lists.golden", 53 }, 54 { 55 in: "../testdata/attr_sep.dot", 56 out: "../testdata/attr_sep.golden", 57 }, 58 {in: "../testdata/subgraph_vertex.dot"}, 59 {in: "../testdata/port.dot"}, 60 {in: "../testdata/quoted_id.dot"}, 61 { 62 in: "../testdata/backslash_newline_id.dot", 63 out: "../testdata/backslash_newline_id.golden", 64 }, 65 } 66 for _, g := range golden { 67 file, err := dot.ParseFile(g.in) 68 if err != nil { 69 t.Errorf("%q: unable to parse file; %v", g.in, err) 70 continue 71 } 72 // If no output path is specified, the input is already golden. 73 out := g.in 74 if len(g.out) > 0 { 75 out = g.out 76 } 77 buf, err := ioutil.ReadFile(out) 78 if err != nil { 79 t.Errorf("%q: unable to read file; %v", g.in, err) 80 continue 81 } 82 got := file.String() 83 // Remove trailing newline. 84 want := string(bytes.TrimSpace(buf)) 85 if got != want { 86 t.Errorf("%q: graph mismatch; expected `%s`, got `%s`", g.in, want, got) 87 } 88 } 89 } 90 91 func TestParseFuzz(t *testing.T) { 92 r, err := zip.OpenReader("../../fuzz/corpus.zip") 93 if err != nil { 94 if os.IsNotExist(err) { 95 t.Skip("no corpus") 96 } 97 t.Fatalf("failed to open corpus: %v", err) 98 } 99 defer r.Close() 100 101 for _, f := range r.File { 102 rc, err := f.Open() 103 if err != nil { 104 t.Fatalf("failed to open %q: %v", f.Name, err) 105 } 106 func() { 107 defer func() { 108 p := recover() 109 if p != nil { 110 t.Errorf("unexpected panic parsing %q: %v", f.Name, p) 111 } 112 }() 113 114 _, err = dot.Parse(rc) 115 if err != nil { 116 t.Errorf("unexpected error parsing %q: %v", f.Name, err) 117 } 118 }() 119 rc.Close() 120 } 121 } 122 123 func TestParseError(t *testing.T) { 124 golden := []struct { 125 path string 126 want string 127 }{ 128 { 129 path: "../testdata/error.dot", 130 want: `Error in S30: INVALID(0,~), Pos(offset=13, line=2, column=7), expected one of: { } graphx ; -- -> node edge [ = subgraph : id `, 131 }, 132 } 133 for _, g := range golden { 134 _, err := dot.ParseFile(g.path) 135 if err == nil { 136 t.Errorf("%q: expected error, got nil", g.path) 137 continue 138 } 139 got := err.Error() 140 if got != g.want { 141 t.Errorf("%q: error mismatch; expected `%v`, got `%v`", g.path, g.want, got) 142 continue 143 } 144 } 145 }