about summary refs log tree commit diff
diff options
context:
space:
mode:
authorchansuke <chansuke@georepublic.de>2019-06-06 00:55:07 +0900
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-06-16 13:08:09 +0300
commited54d10de6a0b330c9546ba7f7906084404efebe (patch)
tree8ed887895c11491659a7ba04fb582befc6a4e667
parent40a0c835b512599a950f99a09dcf1685f7e1bb65 (diff)
downloadrust-ed54d10de6a0b330c9546ba7f7906084404efebe.tar.gz
rust-ed54d10de6a0b330c9546ba7f7906084404efebe.zip
Separate libgraphviz module
-rw-r--r--src/libgraphviz/lib.rs383
-rw-r--r--src/libgraphviz/tests.rs380
2 files changed, 381 insertions, 382 deletions
diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs
index 489020d4ee7..a34e4fb89ff 100644
--- a/src/libgraphviz/lib.rs
+++ b/src/libgraphviz/lib.rs
@@ -684,385 +684,4 @@ pub fn render_opts<'a, N, E, G, W>(g: &'a G,
 }
 
 #[cfg(test)]
-mod tests {
-    use NodeLabels::*;
-    use super::{Id, Labeller, Nodes, Edges, GraphWalk, render, Style};
-    use super::LabelText::{self, LabelStr, EscStr, HtmlStr};
-    use std::io;
-    use std::io::prelude::*;
-
-    /// each node is an index in a vector in the graph.
-    type Node = usize;
-    struct Edge {
-        from: usize,
-        to: usize,
-        label: &'static str,
-        style: Style,
-    }
-
-    fn edge(from: usize, to: usize, label: &'static str, style: Style) -> Edge {
-        Edge {
-            from,
-            to,
-            label,
-            style,
-        }
-    }
-
-    struct LabelledGraph {
-        /// The name for this graph. Used for labeling generated `digraph`.
-        name: &'static str,
-
-        /// Each node is an index into `node_labels`; these labels are
-        /// used as the label text for each node. (The node *names*,
-        /// which are unique identifiers, are derived from their index
-        /// in this array.)
-        ///
-        /// If a node maps to None here, then just use its name as its
-        /// text.
-        node_labels: Vec<Option<&'static str>>,
-
-        node_styles: Vec<Style>,
-
-        /// Each edge relates a from-index to a to-index along with a
-        /// label; `edges` collects them.
-        edges: Vec<Edge>,
-    }
-
-    // A simple wrapper around LabelledGraph that forces the labels to
-    // be emitted as EscStr.
-    struct LabelledGraphWithEscStrs {
-        graph: LabelledGraph,
-    }
-
-    enum NodeLabels<L> {
-        AllNodesLabelled(Vec<L>),
-        UnlabelledNodes(usize),
-        SomeNodesLabelled(Vec<Option<L>>),
-    }
-
-    type Trivial = NodeLabels<&'static str>;
-
-    impl NodeLabels<&'static str> {
-        fn to_opt_strs(self) -> Vec<Option<&'static str>> {
-            match self {
-                UnlabelledNodes(len) => vec![None; len],
-                AllNodesLabelled(lbls) => lbls.into_iter().map(|l| Some(l)).collect(),
-                SomeNodesLabelled(lbls) => lbls.into_iter().collect(),
-            }
-        }
-
-        fn len(&self) -> usize {
-            match self {
-                &UnlabelledNodes(len) => len,
-                &AllNodesLabelled(ref lbls) => lbls.len(),
-                &SomeNodesLabelled(ref lbls) => lbls.len(),
-            }
-        }
-    }
-
-    impl LabelledGraph {
-        fn new(name: &'static str,
-               node_labels: Trivial,
-               edges: Vec<Edge>,
-               node_styles: Option<Vec<Style>>)
-               -> LabelledGraph {
-            let count = node_labels.len();
-            LabelledGraph {
-                name,
-                node_labels: node_labels.to_opt_strs(),
-                edges,
-                node_styles: match node_styles {
-                    Some(nodes) => nodes,
-                    None => vec![Style::None; count],
-                },
-            }
-        }
-    }
-
-    impl LabelledGraphWithEscStrs {
-        fn new(name: &'static str,
-               node_labels: Trivial,
-               edges: Vec<Edge>)
-               -> LabelledGraphWithEscStrs {
-            LabelledGraphWithEscStrs { graph: LabelledGraph::new(name, node_labels, edges, None) }
-        }
-    }
-
-    fn id_name<'a>(n: &Node) -> Id<'a> {
-        Id::new(format!("N{}", *n)).unwrap()
-    }
-
-    impl<'a> Labeller<'a> for LabelledGraph {
-        type Node = Node;
-        type Edge = &'a Edge;
-        fn graph_id(&'a self) -> Id<'a> {
-            Id::new(self.name).unwrap()
-        }
-        fn node_id(&'a self, n: &Node) -> Id<'a> {
-            id_name(n)
-        }
-        fn node_label(&'a self, n: &Node) -> LabelText<'a> {
-            match self.node_labels[*n] {
-                Some(l) => LabelStr(l.into()),
-                None => LabelStr(id_name(n).name()),
-            }
-        }
-        fn edge_label(&'a self, e: &&'a Edge) -> LabelText<'a> {
-            LabelStr(e.label.into())
-        }
-        fn node_style(&'a self, n: &Node) -> Style {
-            self.node_styles[*n]
-        }
-        fn edge_style(&'a self, e: &&'a Edge) -> Style {
-            e.style
-        }
-    }
-
-    impl<'a> Labeller<'a> for LabelledGraphWithEscStrs {
-        type Node = Node;
-        type Edge = &'a Edge;
-        fn graph_id(&'a self) -> Id<'a> {
-            self.graph.graph_id()
-        }
-        fn node_id(&'a self, n: &Node) -> Id<'a> {
-            self.graph.node_id(n)
-        }
-        fn node_label(&'a self, n: &Node) -> LabelText<'a> {
-            match self.graph.node_label(n) {
-                LabelStr(s) | EscStr(s) | HtmlStr(s) => EscStr(s),
-            }
-        }
-        fn edge_label(&'a self, e: &&'a Edge) -> LabelText<'a> {
-            match self.graph.edge_label(e) {
-                LabelStr(s) | EscStr(s) | HtmlStr(s) => EscStr(s),
-            }
-        }
-    }
-
-    impl<'a> GraphWalk<'a> for LabelledGraph {
-        type Node = Node;
-        type Edge = &'a Edge;
-        fn nodes(&'a self) -> Nodes<'a, Node> {
-            (0..self.node_labels.len()).collect()
-        }
-        fn edges(&'a self) -> Edges<'a, &'a Edge> {
-            self.edges.iter().collect()
-        }
-        fn source(&'a self, edge: &&'a Edge) -> Node {
-            edge.from
-        }
-        fn target(&'a self, edge: &&'a Edge) -> Node {
-            edge.to
-        }
-    }
-
-    impl<'a> GraphWalk<'a> for LabelledGraphWithEscStrs {
-        type Node = Node;
-        type Edge = &'a Edge;
-        fn nodes(&'a self) -> Nodes<'a, Node> {
-            self.graph.nodes()
-        }
-        fn edges(&'a self) -> Edges<'a, &'a Edge> {
-            self.graph.edges()
-        }
-        fn source(&'a self, edge: &&'a Edge) -> Node {
-            edge.from
-        }
-        fn target(&'a self, edge: &&'a Edge) -> Node {
-            edge.to
-        }
-    }
-
-    fn test_input(g: LabelledGraph) -> io::Result<String> {
-        let mut writer = Vec::new();
-        render(&g, &mut writer).unwrap();
-        let mut s = String::new();
-        Read::read_to_string(&mut &*writer, &mut s)?;
-        Ok(s)
-    }
-
-    // All of the tests use raw-strings as the format for the expected outputs,
-    // so that you can cut-and-paste the content into a .dot file yourself to
-    // see what the graphviz visualizer would produce.
-
-    #[test]
-    fn empty_graph() {
-        let labels: Trivial = UnlabelledNodes(0);
-        let r = test_input(LabelledGraph::new("empty_graph", labels, vec![], None));
-        assert_eq!(r.unwrap(),
-r#"digraph empty_graph {
-}
-"#);
-    }
-
-    #[test]
-    fn single_node() {
-        let labels: Trivial = UnlabelledNodes(1);
-        let r = test_input(LabelledGraph::new("single_node", labels, vec![], None));
-        assert_eq!(r.unwrap(),
-r#"digraph single_node {
-    N0[label="N0"];
-}
-"#);
-    }
-
-    #[test]
-    fn single_node_with_style() {
-        let labels: Trivial = UnlabelledNodes(1);
-        let styles = Some(vec![Style::Dashed]);
-        let r = test_input(LabelledGraph::new("single_node", labels, vec![], styles));
-        assert_eq!(r.unwrap(),
-r#"digraph single_node {
-    N0[label="N0"][style="dashed"];
-}
-"#);
-    }
-
-    #[test]
-    fn single_edge() {
-        let labels: Trivial = UnlabelledNodes(2);
-        let result = test_input(LabelledGraph::new("single_edge",
-                                                   labels,
-                                                   vec![edge(0, 1, "E", Style::None)],
-                                                   None));
-        assert_eq!(result.unwrap(),
-r#"digraph single_edge {
-    N0[label="N0"];
-    N1[label="N1"];
-    N0 -> N1[label="E"];
-}
-"#);
-    }
-
-    #[test]
-    fn single_edge_with_style() {
-        let labels: Trivial = UnlabelledNodes(2);
-        let result = test_input(LabelledGraph::new("single_edge",
-                                                   labels,
-                                                   vec![edge(0, 1, "E", Style::Bold)],
-                                                   None));
-        assert_eq!(result.unwrap(),
-r#"digraph single_edge {
-    N0[label="N0"];
-    N1[label="N1"];
-    N0 -> N1[label="E"][style="bold"];
-}
-"#);
-    }
-
-    #[test]
-    fn test_some_labelled() {
-        let labels: Trivial = SomeNodesLabelled(vec![Some("A"), None]);
-        let styles = Some(vec![Style::None, Style::Dotted]);
-        let result = test_input(LabelledGraph::new("test_some_labelled",
-                                                   labels,
-                                                   vec![edge(0, 1, "A-1", Style::None)],
-                                                   styles));
-        assert_eq!(result.unwrap(),
-r#"digraph test_some_labelled {
-    N0[label="A"];
-    N1[label="N1"][style="dotted"];
-    N0 -> N1[label="A-1"];
-}
-"#);
-    }
-
-    #[test]
-    fn single_cyclic_node() {
-        let labels: Trivial = UnlabelledNodes(1);
-        let r = test_input(LabelledGraph::new("single_cyclic_node",
-                                              labels,
-                                              vec![edge(0, 0, "E", Style::None)],
-                                              None));
-        assert_eq!(r.unwrap(),
-r#"digraph single_cyclic_node {
-    N0[label="N0"];
-    N0 -> N0[label="E"];
-}
-"#);
-    }
-
-    #[test]
-    fn hasse_diagram() {
-        let labels = AllNodesLabelled(vec!["{x,y}", "{x}", "{y}", "{}"]);
-        let r = test_input(LabelledGraph::new("hasse_diagram",
-                                              labels,
-                                              vec![edge(0, 1, "", Style::None),
-                                                   edge(0, 2, "", Style::None),
-                                                   edge(1, 3, "", Style::None),
-                                                   edge(2, 3, "", Style::None)],
-                                              None));
-        assert_eq!(r.unwrap(),
-r#"digraph hasse_diagram {
-    N0[label="{x,y}"];
-    N1[label="{x}"];
-    N2[label="{y}"];
-    N3[label="{}"];
-    N0 -> N1[label=""];
-    N0 -> N2[label=""];
-    N1 -> N3[label=""];
-    N2 -> N3[label=""];
-}
-"#);
-    }
-
-    #[test]
-    fn left_aligned_text() {
-        let labels = AllNodesLabelled(vec![
-            "if test {\
-           \\l    branch1\
-           \\l} else {\
-           \\l    branch2\
-           \\l}\
-           \\lafterward\
-           \\l",
-            "branch1",
-            "branch2",
-            "afterward"]);
-
-        let mut writer = Vec::new();
-
-        let g = LabelledGraphWithEscStrs::new("syntax_tree",
-                                              labels,
-                                              vec![edge(0, 1, "then", Style::None),
-                                                   edge(0, 2, "else", Style::None),
-                                                   edge(1, 3, ";", Style::None),
-                                                   edge(2, 3, ";", Style::None)]);
-
-        render(&g, &mut writer).unwrap();
-        let mut r = String::new();
-        Read::read_to_string(&mut &*writer, &mut r).unwrap();
-
-        assert_eq!(r,
-r#"digraph syntax_tree {
-    N0[label="if test {\l    branch1\l} else {\l    branch2\l}\lafterward\l"];
-    N1[label="branch1"];
-    N2[label="branch2"];
-    N3[label="afterward"];
-    N0 -> N1[label="then"];
-    N0 -> N2[label="else"];
-    N1 -> N3[label=";"];
-    N2 -> N3[label=";"];
-}
-"#);
-    }
-
-    #[test]
-    fn simple_id_construction() {
-        let id1 = Id::new("hello");
-        match id1 {
-            Ok(_) => {}
-            Err(..) => panic!("'hello' is not a valid value for id anymore"),
-        }
-    }
-
-    #[test]
-    fn badly_formatted_id() {
-        let id2 = Id::new("Weird { struct : ure } !!!");
-        match id2 {
-            Ok(_) => panic!("graphviz id suddenly allows spaces, brackets and stuff"),
-            Err(..) => {}
-        }
-    }
-}
+mod tests;
diff --git a/src/libgraphviz/tests.rs b/src/libgraphviz/tests.rs
new file mode 100644
index 00000000000..2f713579b17
--- /dev/null
+++ b/src/libgraphviz/tests.rs
@@ -0,0 +1,380 @@
+use NodeLabels::*;
+use super::{Id, Labeller, Nodes, Edges, GraphWalk, render, Style};
+use super::LabelText::{self, LabelStr, EscStr, HtmlStr};
+use std::io;
+use std::io::prelude::*;
+
+/// each node is an index in a vector in the graph.
+type Node = usize;
+struct Edge {
+    from: usize,
+    to: usize,
+    label: &'static str,
+    style: Style,
+}
+
+fn edge(from: usize, to: usize, label: &'static str, style: Style) -> Edge {
+    Edge {
+        from,
+        to,
+        label,
+        style,
+    }
+}
+
+struct LabelledGraph {
+    /// The name for this graph. Used for labeling generated `digraph`.
+    name: &'static str,
+
+    /// Each node is an index into `node_labels`; these labels are
+    /// used as the label text for each node. (The node *names*,
+    /// which are unique identifiers, are derived from their index
+    /// in this array.)
+    ///
+    /// If a node maps to None here, then just use its name as its
+    /// text.
+    node_labels: Vec<Option<&'static str>>,
+
+    node_styles: Vec<Style>,
+
+    /// Each edge relates a from-index to a to-index along with a
+    /// label; `edges` collects them.
+    edges: Vec<Edge>,
+}
+
+// A simple wrapper around LabelledGraph that forces the labels to
+// be emitted as EscStr.
+struct LabelledGraphWithEscStrs {
+    graph: LabelledGraph,
+}
+
+enum NodeLabels<L> {
+    AllNodesLabelled(Vec<L>),
+    UnlabelledNodes(usize),
+    SomeNodesLabelled(Vec<Option<L>>),
+}
+
+type Trivial = NodeLabels<&'static str>;
+
+impl NodeLabels<&'static str> {
+    fn to_opt_strs(self) -> Vec<Option<&'static str>> {
+        match self {
+            UnlabelledNodes(len) => vec![None; len],
+            AllNodesLabelled(lbls) => lbls.into_iter().map(|l| Some(l)).collect(),
+            SomeNodesLabelled(lbls) => lbls.into_iter().collect(),
+        }
+    }
+
+    fn len(&self) -> usize {
+        match self {
+            &UnlabelledNodes(len) => len,
+            &AllNodesLabelled(ref lbls) => lbls.len(),
+            &SomeNodesLabelled(ref lbls) => lbls.len(),
+        }
+    }
+}
+
+impl LabelledGraph {
+    fn new(name: &'static str,
+           node_labels: Trivial,
+           edges: Vec<Edge>,
+           node_styles: Option<Vec<Style>>)
+           -> LabelledGraph {
+        let count = node_labels.len();
+        LabelledGraph {
+            name,
+            node_labels: node_labels.to_opt_strs(),
+            edges,
+            node_styles: match node_styles {
+                Some(nodes) => nodes,
+                None => vec![Style::None; count],
+            },
+        }
+    }
+}
+
+impl LabelledGraphWithEscStrs {
+    fn new(name: &'static str,
+           node_labels: Trivial,
+           edges: Vec<Edge>)
+           -> LabelledGraphWithEscStrs {
+        LabelledGraphWithEscStrs { graph: LabelledGraph::new(name, node_labels, edges, None) }
+    }
+}
+
+fn id_name<'a>(n: &Node) -> Id<'a> {
+    Id::new(format!("N{}", *n)).unwrap()
+}
+
+impl<'a> Labeller<'a> for LabelledGraph {
+    type Node = Node;
+    type Edge = &'a Edge;
+    fn graph_id(&'a self) -> Id<'a> {
+        Id::new(self.name).unwrap()
+    }
+    fn node_id(&'a self, n: &Node) -> Id<'a> {
+        id_name(n)
+    }
+    fn node_label(&'a self, n: &Node) -> LabelText<'a> {
+        match self.node_labels[*n] {
+            Some(l) => LabelStr(l.into()),
+            None => LabelStr(id_name(n).name()),
+        }
+    }
+    fn edge_label(&'a self, e: &&'a Edge) -> LabelText<'a> {
+        LabelStr(e.label.into())
+    }
+    fn node_style(&'a self, n: &Node) -> Style {
+        self.node_styles[*n]
+    }
+    fn edge_style(&'a self, e: &&'a Edge) -> Style {
+        e.style
+    }
+}
+
+impl<'a> Labeller<'a> for LabelledGraphWithEscStrs {
+    type Node = Node;
+    type Edge = &'a Edge;
+    fn graph_id(&'a self) -> Id<'a> {
+        self.graph.graph_id()
+    }
+    fn node_id(&'a self, n: &Node) -> Id<'a> {
+        self.graph.node_id(n)
+    }
+    fn node_label(&'a self, n: &Node) -> LabelText<'a> {
+        match self.graph.node_label(n) {
+            LabelStr(s) | EscStr(s) | HtmlStr(s) => EscStr(s),
+        }
+    }
+    fn edge_label(&'a self, e: &&'a Edge) -> LabelText<'a> {
+        match self.graph.edge_label(e) {
+            LabelStr(s) | EscStr(s) | HtmlStr(s) => EscStr(s),
+        }
+    }
+}
+
+impl<'a> GraphWalk<'a> for LabelledGraph {
+    type Node = Node;
+    type Edge = &'a Edge;
+    fn nodes(&'a self) -> Nodes<'a, Node> {
+        (0..self.node_labels.len()).collect()
+    }
+    fn edges(&'a self) -> Edges<'a, &'a Edge> {
+        self.edges.iter().collect()
+    }
+    fn source(&'a self, edge: &&'a Edge) -> Node {
+        edge.from
+    }
+    fn target(&'a self, edge: &&'a Edge) -> Node {
+        edge.to
+    }
+}
+
+impl<'a> GraphWalk<'a> for LabelledGraphWithEscStrs {
+    type Node = Node;
+    type Edge = &'a Edge;
+    fn nodes(&'a self) -> Nodes<'a, Node> {
+        self.graph.nodes()
+    }
+    fn edges(&'a self) -> Edges<'a, &'a Edge> {
+        self.graph.edges()
+    }
+    fn source(&'a self, edge: &&'a Edge) -> Node {
+        edge.from
+    }
+    fn target(&'a self, edge: &&'a Edge) -> Node {
+        edge.to
+    }
+}
+
+fn test_input(g: LabelledGraph) -> io::Result<String> {
+    let mut writer = Vec::new();
+    render(&g, &mut writer).unwrap();
+    let mut s = String::new();
+    Read::read_to_string(&mut &*writer, &mut s)?;
+    Ok(s)
+}
+
+// All of the tests use raw-strings as the format for the expected outputs,
+// so that you can cut-and-paste the content into a .dot file yourself to
+// see what the graphviz visualizer would produce.
+
+#[test]
+fn empty_graph() {
+    let labels: Trivial = UnlabelledNodes(0);
+    let r = test_input(LabelledGraph::new("empty_graph", labels, vec![], None));
+    assert_eq!(r.unwrap(),
+r#"digraph empty_graph {
+}
+"#);
+}
+
+#[test]
+fn single_node() {
+    let labels: Trivial = UnlabelledNodes(1);
+    let r = test_input(LabelledGraph::new("single_node", labels, vec![], None));
+    assert_eq!(r.unwrap(),
+r#"digraph single_node {
+    N0[label="N0"];
+}
+"#);
+}
+
+#[test]
+fn single_node_with_style() {
+    let labels: Trivial = UnlabelledNodes(1);
+    let styles = Some(vec![Style::Dashed]);
+    let r = test_input(LabelledGraph::new("single_node", labels, vec![], styles));
+    assert_eq!(r.unwrap(),
+r#"digraph single_node {
+    N0[label="N0"][style="dashed"];
+}
+"#);
+}
+
+#[test]
+fn single_edge() {
+    let labels: Trivial = UnlabelledNodes(2);
+    let result = test_input(LabelledGraph::new("single_edge",
+                                               labels,
+                                               vec![edge(0, 1, "E", Style::None)],
+                                               None));
+    assert_eq!(result.unwrap(),
+r#"digraph single_edge {
+    N0[label="N0"];
+    N1[label="N1"];
+    N0 -> N1[label="E"];
+}
+"#);
+}
+
+#[test]
+fn single_edge_with_style() {
+    let labels: Trivial = UnlabelledNodes(2);
+    let result = test_input(LabelledGraph::new("single_edge",
+                                               labels,
+                                               vec![edge(0, 1, "E", Style::Bold)],
+                                               None));
+    assert_eq!(result.unwrap(),
+r#"digraph single_edge {
+    N0[label="N0"];
+    N1[label="N1"];
+    N0 -> N1[label="E"][style="bold"];
+}
+"#);
+}
+
+#[test]
+fn test_some_labelled() {
+    let labels: Trivial = SomeNodesLabelled(vec![Some("A"), None]);
+    let styles = Some(vec![Style::None, Style::Dotted]);
+    let result = test_input(LabelledGraph::new("test_some_labelled",
+                                               labels,
+                                               vec![edge(0, 1, "A-1", Style::None)],
+                                               styles));
+    assert_eq!(result.unwrap(),
+r#"digraph test_some_labelled {
+    N0[label="A"];
+    N1[label="N1"][style="dotted"];
+    N0 -> N1[label="A-1"];
+}
+"#);
+}
+
+#[test]
+fn single_cyclic_node() {
+    let labels: Trivial = UnlabelledNodes(1);
+    let r = test_input(LabelledGraph::new("single_cyclic_node",
+                                          labels,
+                                          vec![edge(0, 0, "E", Style::None)],
+                                          None));
+    assert_eq!(r.unwrap(),
+r#"digraph single_cyclic_node {
+    N0[label="N0"];
+    N0 -> N0[label="E"];
+}
+"#);
+}
+
+#[test]
+fn hasse_diagram() {
+    let labels = AllNodesLabelled(vec!["{x,y}", "{x}", "{y}", "{}"]);
+    let r = test_input(LabelledGraph::new("hasse_diagram",
+                                          labels,
+                                          vec![edge(0, 1, "", Style::None),
+                                               edge(0, 2, "", Style::None),
+                                               edge(1, 3, "", Style::None),
+                                               edge(2, 3, "", Style::None)],
+                                          None));
+    assert_eq!(r.unwrap(),
+r#"digraph hasse_diagram {
+    N0[label="{x,y}"];
+    N1[label="{x}"];
+    N2[label="{y}"];
+    N3[label="{}"];
+    N0 -> N1[label=""];
+    N0 -> N2[label=""];
+    N1 -> N3[label=""];
+    N2 -> N3[label=""];
+}
+"#);
+}
+
+#[test]
+fn left_aligned_text() {
+    let labels = AllNodesLabelled(vec![
+        "if test {\
+       \\l    branch1\
+       \\l} else {\
+       \\l    branch2\
+       \\l}\
+       \\lafterward\
+       \\l",
+        "branch1",
+        "branch2",
+        "afterward"]);
+
+    let mut writer = Vec::new();
+
+    let g = LabelledGraphWithEscStrs::new("syntax_tree",
+                                          labels,
+                                          vec![edge(0, 1, "then", Style::None),
+                                               edge(0, 2, "else", Style::None),
+                                               edge(1, 3, ";", Style::None),
+                                               edge(2, 3, ";", Style::None)]);
+
+    render(&g, &mut writer).unwrap();
+    let mut r = String::new();
+    Read::read_to_string(&mut &*writer, &mut r).unwrap();
+
+    assert_eq!(r,
+r#"digraph syntax_tree {
+    N0[label="if test {\l    branch1\l} else {\l    branch2\l}\lafterward\l"];
+    N1[label="branch1"];
+    N2[label="branch2"];
+    N3[label="afterward"];
+    N0 -> N1[label="then"];
+    N0 -> N2[label="else"];
+    N1 -> N3[label=";"];
+    N2 -> N3[label=";"];
+}
+"#);
+}
+
+#[test]
+fn simple_id_construction() {
+    let id1 = Id::new("hello");
+    match id1 {
+        Ok(_) => {}
+        Err(..) => panic!("'hello' is not a valid value for id anymore"),
+    }
+}
+
+#[test]
+fn badly_formatted_id() {
+    let id2 = Id::new("Weird { struct : ure } !!!");
+    match id2 {
+        Ok(_) => panic!("graphviz id suddenly allows spaces, brackets and stuff"),
+        Err(..) => {}
+    }
+}