diff --git a/Cargo.lock b/Cargo.lock
index d867090c792f1c1b070978ef18ff52d6b70e9612..ec7537a8e4b6694459f1962eaadc80e200b55c99 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -51,9 +51,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.59"
+version = "1.0.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b"
+checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
 dependencies = [
  "unicode-ident",
 ]
@@ -69,15 +69,15 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.163"
+version = "1.0.164"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
+checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
 
 [[package]]
 name = "serde_derive"
-version = "1.0.163"
+version = "1.0.164"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
+checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/examples/opticscenery.rs b/examples/opticscenery.rs
index 9836238a6d3fd3c518655457ae970c930618be26..03c40a6e4f08e1c936fd9819a614fd5dbc52afa9 100644
--- a/examples/opticscenery.rs
+++ b/examples/opticscenery.rs
@@ -12,7 +12,7 @@ fn main() {
     println!("export to `dot` format: {}", scenery.to_dot());
     let node1 = scenery.add_element("my optic", NodeDummy);
     let node2 = scenery.add_element("my other optic", NodeDummy);
-    if let Ok(_) = scenery.connect_nodes(node1, node2) {
+    if let Ok(_) = scenery.connect_nodes(node1, "rear", node2, "front") {
         let path = "graph.dot";
         let mut output = File::create(path).unwrap();
         write!(output, "{}", scenery.to_dot()).unwrap();
diff --git a/examples/pa_doublepass_graph.rs b/examples/pa_doublepass_graph.rs
index fc975a11a7f260225e7750303226c6ec0cca001e..703e554c6fcfdf49625515dbd7dca4ccadd7ccd6 100644
--- a/examples/pa_doublepass_graph.rs
+++ b/examples/pa_doublepass_graph.rs
@@ -28,12 +28,12 @@ fn main() {
     node.set_inverted(true);
     let n1i = scenery.add_node(node);
 
-    scenery.connect_nodes(n1, n2).unwrap();
-    scenery.connect_nodes(n2, n3).unwrap();
-    scenery.connect_nodes(n3, n4).unwrap();
-    scenery.connect_nodes(n4, n3i).unwrap();
-    scenery.connect_nodes(n3i, n2i).unwrap();
-    scenery.connect_nodes(n2i, n1i).unwrap();
+    scenery.connect_nodes(n1, "rear", n2, "front").unwrap();
+    scenery.connect_nodes(n2, "rear", n3, "front").unwrap();
+    scenery.connect_nodes(n3, "rear", n4, "front").unwrap();
+    scenery.connect_nodes(n4, "rear", n3i, "rear").unwrap();
+    scenery.connect_nodes(n3i, "front", n2i, "rear").unwrap();
+    scenery.connect_nodes(n2i, "front", n1i, "rear").unwrap();
 
     let mut group = NodeGroup::new();
     let g_n1 = group.add_node(OpticNode::new("Beamsplitter", NodeDummy));
diff --git a/examples/uopa_graph.rs b/examples/uopa_graph.rs
index 0a2eb8cc74f404f34d4fe2f542ab562cbd0bfb57..6ffd97592dcfcfe75cc1eeb102d2ad9d43732303 100644
--- a/examples/uopa_graph.rs
+++ b/examples/uopa_graph.rs
@@ -1,5 +1,5 @@
+use opossum::nodes::{NodeBeamSplitter, NodeDummy};
 use opossum::optic_scenery::OpticScenery;
-use opossum::nodes::{NodeDummy, NodeBeamSplitter};
 
 use std::fs::File;
 use std::io::Write;
@@ -21,15 +21,30 @@ fn main() {
     let pump_shg_node = scenery.add_element("Pump SHG", NodeDummy);
     let pump_splitter_node = scenery.add_element("Pump Beam Splitter", NodeBeamSplitter);
 
-    scenery.connect_nodes(pulse_generation_split_node, uOPA_1_node);
-    scenery.connect_nodes(pulse_generation_split_node, pump_pre_amplifier_node);
-    scenery.connect_nodes(pump_pre_amplifier_node, pump_main_amplifier_node);
-    scenery.connect_nodes(pump_main_amplifier_node, pump_compressor_node);
-    scenery.connect_nodes(pump_compressor_node, pump_shg_node);
-    scenery.connect_nodes(pump_shg_node, pump_splitter_node);
-    scenery.connect_nodes(pump_splitter_node, uOPA_1_node);
-    scenery.connect_nodes(uOPA_1_node, uOPA_2_node);
-    scenery.connect_nodes(pump_splitter_node, uOPA_2_node);
+    scenery.connect_nodes(pulse_generation_split_node, "rear", uOPA_1_node, "front");
+    scenery.connect_nodes(
+        pulse_generation_split_node,
+        "rear",
+        pump_pre_amplifier_node,
+        "front",
+    );
+    scenery.connect_nodes(
+        pump_pre_amplifier_node,
+        "rear",
+        pump_main_amplifier_node,
+        "front",
+    );
+    scenery.connect_nodes(
+        pump_main_amplifier_node,
+        "rear",
+        pump_compressor_node,
+        "front",
+    );
+    scenery.connect_nodes(pump_compressor_node, "rear", pump_shg_node, "front");
+    scenery.connect_nodes(pump_shg_node, "rear", pump_splitter_node, "front");
+    scenery.connect_nodes(pump_splitter_node, "transmitted", uOPA_1_node, "front").unwrap();
+    scenery.connect_nodes(uOPA_1_node, "rear", uOPA_2_node, "front");
+    scenery.connect_nodes(pump_splitter_node, "reflected", uOPA_2_node, "front").unwrap();
 
     let mut scenery_2 = OpticScenery::new();
     scenery_2.set_description("PHELIX uOPA Pump Pre-Amplifier".into());
@@ -54,25 +69,25 @@ fn main() {
     let monitor2_node = scenery_2.add_element("Monitor", NodeDummy);
     let monitor3_node = scenery_2.add_element("Monitor", NodeDummy);
 
-    scenery_2.connect_nodes(spm_node, circ1_node);
-    scenery_2.connect_nodes(circ1_node, circ2_node);
-    scenery_2.connect_nodes(circ2_node, cfbg_node);
-    scenery_2.connect_nodes(cfbg_node, circ3_node);
-    scenery_2.connect_nodes(cfbg_node, monitor1_node);
-    scenery_2.connect_nodes(circ3_node, isolator1_node);
-    scenery_2.connect_nodes(isolator1_node, tap1_node);
-    scenery_2.connect_nodes(tap1_node, monitor2_node);
-    scenery_2.connect_nodes(tap1_node, wdm_node);
-    scenery_2.connect_nodes(diode1_node, wdm_node);
-    scenery_2.connect_nodes(wdm_node, yb_fiber1_node);
-    scenery_2.connect_nodes(yb_fiber1_node, tap2_node);
-    scenery_2.connect_nodes(tap2_node, monitor3_node);
-    scenery_2.connect_nodes(tap2_node, aom_node);
-    scenery_2.connect_nodes(aom_node, isolator2_node);
-    scenery_2.connect_nodes(isolator2_node, yb_fiber2_node_node);
-    scenery_2.connect_nodes(yb_fiber2_node_node, dichroic_node);
-    scenery_2.connect_nodes(dichroic_node, dichroic_node);
-    scenery_2.connect_nodes(diode2_node, dichroic_node);
+    scenery_2.connect_nodes(spm_node, "rear", circ1_node, "front");
+    scenery_2.connect_nodes(circ1_node, "rear", circ2_node, "front");
+    scenery_2.connect_nodes(circ2_node, "rear", cfbg_node, "front");
+    scenery_2.connect_nodes(cfbg_node, "rear", circ3_node, "front");
+    scenery_2.connect_nodes(cfbg_node, "rear", monitor1_node, "front");
+    scenery_2.connect_nodes(circ3_node, "rear", isolator1_node, "front");
+    scenery_2.connect_nodes(isolator1_node, "rear", tap1_node, "front");
+    scenery_2.connect_nodes(tap1_node, "rear", monitor2_node, "front");
+    scenery_2.connect_nodes(tap1_node, "rear", wdm_node, "front");
+    scenery_2.connect_nodes(diode1_node, "rear", wdm_node, "front");
+    scenery_2.connect_nodes(wdm_node, "rear", yb_fiber1_node, "front");
+    scenery_2.connect_nodes(yb_fiber1_node, "rear", tap2_node, "front");
+    scenery_2.connect_nodes(tap2_node, "rear", monitor3_node, "front");
+    scenery_2.connect_nodes(tap2_node, "rear", aom_node, "front");
+    scenery_2.connect_nodes(aom_node, "rear", isolator2_node, "front");
+    scenery_2.connect_nodes(isolator2_node, "rear", yb_fiber2_node_node, "front");
+    scenery_2.connect_nodes(yb_fiber2_node_node, "rear", dichroic_node, "front");
+    scenery_2.connect_nodes(dichroic_node, "rear", dichroic_node, "front");
+    scenery_2.connect_nodes(diode2_node, "rear", dichroic_node, "front");
 
     let mut scenery_3 = OpticScenery::new();
     scenery_3.set_description("PHELIX uOPA Pump Regenerative Main-Amplifier".into());
diff --git a/src/error.rs b/src/error.rs
index 01e7892a3b579a78449b237bc1feec208aec2046..82d7fe857ebb0081e135a9e593687a3ccb4c766d 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,7 +1,33 @@
+use std::{error::Error, fmt::Display};
+
 #[derive(Debug, Clone)]
 pub enum OpossumError {
-  OpticScenery(String),
-  OpticGroup(String),
-  OpticPort(String),
-  Other(String)
+    OpticScenery(String),
+    OpticGroup(String),
+    OpticPort(String),
+    Other(String),
+}
+
+impl Display for OpossumError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            OpossumError::OpticScenery(m) => {
+                write!(f, "Opossum Error::OpticScenery::{}", m)
+            }
+            OpossumError::OpticGroup(m) => {
+                write!(f, "Opossum Error::OpticGroup::{}", m)
+            }
+            OpossumError::OpticPort(m) => {
+                write!(f, "Opossum Error::OpticPort::{}", m)
+            }
+            OpossumError::Other(m) => write!(f, "Opossum Error::Other::{}", m),
+        }
+    }
+}
+impl Error for OpossumError {}
+
+impl std::convert::From<String> for OpossumError {
+    fn from(msg: String) -> Self {
+        Self::Other(msg)
+    }
 }
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index eb6cc7d179992efdacd72efdebcdd7773240ec9b..66cf11c6e602e1caf11af44d98a7db253355c72f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,6 +4,8 @@
 pub mod optic_scenery;
 /// The basic structure representing an optical element
 pub mod optic_node;
+pub mod light;
+
 pub mod optic_ports;
 
 pub mod nodes;
diff --git a/src/light.rs b/src/light.rs
new file mode 100644
index 0000000000000000000000000000000000000000..2a8f4c3bbfcfbc9ab5bdb2f170cdd09a27c7ad6b
--- /dev/null
+++ b/src/light.rs
@@ -0,0 +1,59 @@
+#[derive(Debug)]
+pub struct Light {
+    src_port: String,
+    target_port: String,
+}
+
+impl Light {
+    pub fn new(src_port: &str, target_port: &str) -> Self {
+        Self {
+            src_port: src_port.into(),
+            target_port: target_port.into(),
+        }
+    }
+    pub fn src_port(&self) -> &str {
+        self.src_port.as_ref()
+    }
+    pub fn target_port(&self) -> &str {
+        self.target_port.as_ref()
+    }
+    pub fn set_src_port(&mut self, src_port: String) {
+        self.src_port = src_port;
+    }
+    pub fn set_target_port(&mut self, target_port: String) {
+        self.target_port = target_port;
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    #[test]
+    fn new() {
+        let light = Light::new("test1", "test2");
+        assert_eq!(light.src_port, "test1");
+        assert_eq!(light.target_port, "test2");
+    }
+    #[test]
+    fn src_port() {
+        let light = Light::new("test1", "test2");
+        assert_eq!(light.src_port(), "test1");
+    }
+    #[test]
+    fn target_port() {
+        let light = Light::new("test1", "test2");
+        assert_eq!(light.target_port(), "test2");
+    }
+    #[test]
+    fn set_src_port() {
+        let mut light = Light::new("test1", "test2");
+        light.set_src_port("test3".into());
+        assert_eq!(light.src_port, "test3");
+    }
+    #[test]
+    fn set_target_port() {
+        let mut light = Light::new("test1", "test2");
+        light.set_target_port("test3".into());
+        assert_eq!(light.target_port, "test3");
+    }
+}
diff --git a/src/nodes/node_reference.rs b/src/nodes/node_reference.rs
index 81e4016676e3f9d01dd92f6031e02b79489cc39d..330ddaa550e558b824e9da027bb9dc7ededb4799 100644
--- a/src/nodes/node_reference.rs
+++ b/src/nodes/node_reference.rs
@@ -1,17 +1,19 @@
+use std::rc::{Weak, Rc};
+
 use crate::optic_node::{OpticNode, Optical};
 
 /// A virtual component referring to another existing component. This node type is necessary in order to model resonators (loops) or double-pass systems.
-pub struct NodeReference<'a> {
-    reference: &'a OpticNode,
+pub struct NodeReference {
+    reference: Rc<OpticNode>,
 }
 
-impl<'a> NodeReference<'a> {
-    pub fn new(node: &'a OpticNode) -> Self {
+impl NodeReference {
+    pub fn new(node: Rc<OpticNode>) -> Self {
         Self { reference: node }
     }
 }
 
-impl<'a> Optical for NodeReference<'a> {
+impl Optical for NodeReference {
     fn node_type(&self) -> &str {
         "reference"
     }
diff --git a/src/optic_node.rs b/src/optic_node.rs
index 62a28f24fc047768d03545aae1494ad8319cde47..d0de2252931b5eec20a19db6f7011e09df3ede18 100644
--- a/src/optic_node.rs
+++ b/src/optic_node.rs
@@ -1,4 +1,4 @@
-use std::fmt::Debug;
+use std::{fmt::Debug, rc::Rc};
 
 use crate::optic_ports::OpticPorts;
 /// An [`OpticNode`] is the basic struct representing an optical component.
@@ -18,7 +18,7 @@ impl OpticNode {
     /// use opossum::optic_node::OpticNode;
     /// use opossum::nodes::NodeDummy;
     ///
-    /// let node=OpticNode::new("My node", Box::new(NodeDummy));
+    /// let node=OpticNode::new("My node", NodeDummy);
     /// ```
     pub fn new<T: Optical+ 'static>(name: &str, node_type: T) -> Self {
         let ports=node_type.ports();
diff --git a/src/optic_scenery.rs b/src/optic_scenery.rs
index cccc6d8ad4b3ac8131c0161d123a67adf0d3837d..d733d21e39e193a85ae34abd8f7102f5b008fc6b 100644
--- a/src/optic_scenery.rs
+++ b/src/optic_scenery.rs
@@ -1,4 +1,7 @@
+use std::rc::Rc;
+
 use crate::error::OpossumError;
+use crate::light::Light;
 use crate::optic_node::{OpticNode, Optical};
 use petgraph::algo::*;
 use petgraph::prelude::{DiGraph, EdgeIndex, NodeIndex};
@@ -9,7 +12,7 @@ type Result<T> = std::result::Result<T, OpossumError>;
 /// to be added to this structure in order to be considered for an analysis.
 #[derive(Default, Debug)]
 pub struct OpticScenery {
-    g: DiGraph<OpticNode, ()>,
+    g: DiGraph<Rc<OpticNode>, Light>,
     description: String,
 }
 
@@ -23,7 +26,7 @@ impl OpticScenery {
     /// This command just adds an [`OpticNode`] to the graph. It does not connect
     /// it to existing nodes in the graph. The given optical element is consumed (owned) by the [`OpticScenery`].
     pub fn add_node(&mut self, node: OpticNode) -> NodeIndex {
-        self.g.add_node(node)
+        self.g.add_node(Rc::new(node))
     }
     /// Add a given optical element to the graph of this [`OpticScenery`].
     ///
@@ -31,7 +34,7 @@ impl OpticScenery {
     /// it to existing nodes in the graph. The given optical element is consumed (owned) by the [`OpticScenery`]. Internally the corresponding [`OpticNode`] is
     /// automatically generated. It serves as a short-cut to the `add_node` function.
     pub fn add_element<T: Optical + 'static>(&mut self, name: &str, t: T) -> NodeIndex {
-        self.g.add_node(OpticNode::new(name, t))
+        self.g.add_node(Rc::new(OpticNode::new(name, t)))
     }
     /// Get reference of [`OpticNode`].
     ///
@@ -50,19 +53,51 @@ impl OpticScenery {
     pub fn connect_nodes(
         &mut self,
         src_node: NodeIndex,
+        src_port: &str,
         target_node: NodeIndex,
+        target_port: &str,
     ) -> Result<EdgeIndex> {
-        if self.g.node_weight(src_node).is_none() {
+        if let Some(source) = self.g.node_weight(src_node) {
+            if !source.ports().outputs().contains(&src_port.into()) {
+                return Err(OpossumError::OpticScenery(format!(
+                    "source node {} does not have a port {}",
+                    source.name(),
+                    src_port
+                )));
+            }
+        } else {
             return Err(OpossumError::OpticScenery(
-                "source node with gievn index does not exist".into(),
+                "source node with given index does not exist".into(),
             ));
         }
-        if self.g.node_weight(target_node).is_none() {
+        if let Some(target) = self.g.node_weight(target_node) {
+            if !target.ports().inputs().contains(&target_port.into()) {
+                return Err(OpossumError::OpticScenery(format!(
+                    "target node {} does not have a port {}",
+                    target.name(),
+                    target_port
+                )));
+            }
+        } else {
             return Err(OpossumError::OpticScenery(
                 "target node with given index does not exist".into(),
             ));
         }
-        let edge_index = self.g.add_edge(src_node, target_node, ());
+        if self.src_node_port_exists(src_node, src_port) {
+            return Err(OpossumError::OpticScenery(format!(
+                "src node with given port {} is already connected",
+                src_port
+            )));
+        }
+        if self.target_node_port_exists(src_node, src_port) {
+            return Err(OpossumError::OpticScenery(format!(
+                "target node with given port {} is already connected",
+                target_port
+            )));
+        }
+        let edge_index = self
+            .g
+            .add_edge(src_node, target_node, Light::new(src_port, target_port));
         if is_cyclic_directed(&self.g) {
             self.g.remove_edge(edge_index);
             return Err(OpossumError::OpticScenery(
@@ -71,6 +106,30 @@ impl OpticScenery {
         }
         Ok(edge_index)
     }
+    fn src_node_port_exists(&self, src_node: NodeIndex, src_port: &str) -> bool {
+        self.g
+            .edges_directed(src_node, petgraph::Direction::Outgoing)
+            .any(|e| e.weight().src_port() == src_port)
+    }
+    fn target_node_port_exists(&self, target_node: NodeIndex, target_port: &str) -> bool {
+        self.g
+            .edges_directed(target_node, petgraph::Direction::Incoming)
+            .any(|e| e.weight().target_port() == target_port)
+    }
+    /// Return a reference to the [`OpticNode`] specifiec by the node index.
+    /// 
+    /// This function is mainly useful for setting up a reference node.
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if the node does not exist.
+    pub fn node_ref(&self, node: NodeIndex) ->Result<Rc<OpticNode>> {
+        if let Some(node) = self.g.node_weight(node) {
+            Ok(node.to_owned())
+        } else {
+            Err(OpossumError::OpticScenery("node index does not exist".into()))
+        }
+    }
     /// Export the optic graph into the `dot` format to be used in combination with the [`graphviz`](https://graphviz.org/) software.
     pub fn to_dot(&self) -> String {
         let mut dot_string = "digraph {\n".to_owned();
@@ -83,11 +142,14 @@ impl OpticScenery {
             dot_string += &node.to_dot(&format!("i{}", node_idx.index()));
         }
         for edge in self.g.edge_indices() {
+            let light=self.g.edge_weight(edge).unwrap();
             let end_nodes = self.g.edge_endpoints(edge).unwrap();
             dot_string.push_str(&format!(
-                "  i{} -> i{}\n",
+                "  i{} -> i{} [label=\"{}->{}\"]\n",
                 end_nodes.0.index(),
-                end_nodes.1.index()
+                end_nodes.1.index(),
+                light.src_port(),
+                light.target_port()
             ));
         }
         dot_string += "}";
@@ -135,7 +197,7 @@ mod test {
         let mut scenery = OpticScenery::new();
         let n1 = scenery.add_element("Test", NodeDummy);
         let n2 = scenery.add_element("Test", NodeDummy);
-        assert!(scenery.connect_nodes(n1, n2).is_ok());
+        assert!(scenery.connect_nodes(n1, "rear", n2, "front").is_ok());
         assert_eq!(scenery.g.edge_count(), 1);
     }
     #[test]
@@ -143,16 +205,20 @@ mod test {
         let mut scenery = OpticScenery::new();
         let n1 = scenery.add_element("Test", NodeDummy);
         let n2 = scenery.add_element("Test", NodeDummy);
-        assert!(scenery.connect_nodes(n1, NodeIndex::new(5)).is_err());
-        assert!(scenery.connect_nodes(NodeIndex::new(5), n2).is_err());
+        assert!(scenery
+            .connect_nodes(n1, "rear", NodeIndex::new(5), "front")
+            .is_err());
+        assert!(scenery
+            .connect_nodes(NodeIndex::new(5), "rear", n2, "front")
+            .is_err());
     }
     #[test]
     fn connect_nodes_loop_error() {
         let mut scenery = OpticScenery::new();
         let n1 = scenery.add_element("Test", NodeDummy);
         let n2 = scenery.add_element("Test", NodeDummy);
-        assert!(scenery.connect_nodes(n1, n2).is_ok());
-        assert!(scenery.connect_nodes(n2, n1).is_err());
+        assert!(scenery.connect_nodes(n1, "rear", n2, "front").is_ok());
+        assert!(scenery.connect_nodes(n2, "rear", n1, "front").is_err());
         assert_eq!(scenery.g.edge_count(), 1);
     }
     #[test]
@@ -175,12 +241,12 @@ mod test {
     fn to_dot_with_edge() {
         let mut scenery = OpticScenery::new();
         scenery.set_description("SceneryTest".into());
-        let n1 =  scenery.add_element("Test1", NodeDummy);
-        let n2 =  scenery.add_element("Test2", NodeDummy);
-        if let Ok(_) = scenery.connect_nodes(n1, n2) {
+        let n1 = scenery.add_element("Test1", NodeDummy);
+        let n2 = scenery.add_element("Test2", NodeDummy);
+        if let Ok(_) = scenery.connect_nodes(n1, "rear", n2, "front") {
             assert_eq!(
                 scenery.to_dot(),
-                "digraph {\n  label=\"SceneryTest\"\n  fontname=\"Helvetica,Arial,sans-serif\"\n  node [fontname=\"Helvetica,Arial,sans-serif\"]\n  edge [fontname=\"Helvetica,Arial,sans-serif\"]\n  i0 [label=\"Test1\"]\n  i1 [label=\"Test2\"]\n  i0 -> i1\n}"
+                "digraph {\n  label=\"SceneryTest\"\n  fontname=\"Helvetica,Arial,sans-serif\"\n  node [fontname=\"Helvetica,Arial,sans-serif\"]\n  edge [fontname=\"Helvetica,Arial,sans-serif\"]\n  i0 [label=\"Test1\"]\n  i1 [label=\"Test2\"]\n  i0 -> i1 [label=\"rear->front\"]\n}"
             );
         } else {
             assert!(false);