@Test
  public void testGetAllEdgesWithDelete() {
    graph = createGraph();
    NodeAccess na = graph.getNodeAccess();
    na.setNode(0, 0, 5);
    na.setNode(1, 1, 5);
    na.setNode(2, 2, 5);
    na.setNode(3, 3, 5);
    graph.edge(0, 1, 1, true);
    graph.edge(0, 2, 1, true);
    graph.edge(1, 2, 1, true);
    graph.edge(2, 3, 1, true);
    AllEdgesIterator iter = graph.getAllEdges();
    assertEquals(4, GHUtility.count(iter));
    assertEquals(4, iter.getMaxId());

    // delete
    graph.markNodeRemoved(1);
    graph.optimize();
    iter = graph.getAllEdges();
    assertEquals(2, GHUtility.count(iter));
    assertEquals(4, iter.getMaxId());

    iter = graph.getAllEdges();
    iter.next();
    EdgeIteratorState eState = iter.detach(false);
    assertEquals(iter.toString(), eState.toString());
    iter.next();
    assertNotEquals(iter.toString(), eState.toString());

    EdgeIteratorState eState2 = iter.detach(true);
    assertEquals(iter.getAdjNode(), eState2.getBaseNode());
    iter.next();
    assertNotEquals(iter.getAdjNode(), eState2.getBaseNode());
  }
 @Test
 public void testEdgeReturn() {
   graph = createGraph();
   EdgeIteratorState iter =
       graph.edge(4, 10).setDistance(100).setFlags(carEncoder.setProperties(10, true, false));
   assertEquals(4, iter.getBaseNode());
   assertEquals(10, iter.getAdjNode());
   iter = graph.edge(14, 10).setDistance(100).setFlags(carEncoder.setProperties(10, true, false));
   assertEquals(14, iter.getBaseNode());
   assertEquals(10, iter.getAdjNode());
 }
  @Test
  public void testDetachEdge() {
    graph = createGraph();
    graph.edge(0, 1, 2, true);
    long flags = carEncoder.setProperties(10, true, false);
    graph.edge(0, 2, 2, true).setWayGeometry(Helper.createPointList(1, 2, 3, 4)).setFlags(flags);
    graph.edge(1, 2, 2, true);

    EdgeIterator iter = graph.createEdgeExplorer().setBaseNode(0);
    try {
      // currently not possible to detach without next, without introducing a new property inside
      // EdgeIterable
      iter.detach(false);
      assertTrue(false);
    } catch (Exception ex) {
    }

    iter.next();
    EdgeIteratorState edgeState2 = iter.detach(false);
    assertEquals(2, iter.getAdjNode());
    assertEquals(1, edgeState2.fetchWayGeometry(0).getLatitude(0), 1e-1);
    assertEquals(2, edgeState2.getAdjNode());
    assertTrue(carEncoder.isBool(edgeState2.getFlags(), FlagEncoder.K_FORWARD));

    EdgeIteratorState edgeState3 = iter.detach(true);
    assertEquals(0, edgeState3.getAdjNode());
    assertEquals(2, edgeState3.getBaseNode());
    assertEquals(3, edgeState3.fetchWayGeometry(0).getLatitude(0), 1e-1);
    assertFalse(carEncoder.isBool(edgeState3.getFlags(), FlagEncoder.K_FORWARD));
    assertEquals(GHUtility.getEdge(graph, 0, 2).getFlags(), edgeState2.getFlags());
    assertEquals(GHUtility.getEdge(graph, 2, 0).getFlags(), edgeState3.getFlags());

    iter.next();
    assertEquals(1, iter.getAdjNode());
    assertEquals(2, edgeState2.getAdjNode());
    assertEquals(2, edgeState3.getBaseNode());

    assertEquals(0, iter.fetchWayGeometry(0).size());
    assertEquals(1, edgeState2.fetchWayGeometry(0).getLatitude(0), 1e-1);
    assertEquals(3, edgeState3.fetchWayGeometry(0).getLatitude(0), 1e-1);

    // #162 a directed self referencing edge should be able to reverse its state too
    graph.edge(3, 3, 2, true).setFlags(flags);
    EdgeIterator iter2 = graph.createEdgeExplorer().setBaseNode(3);
    iter2.next();
    assertEquals(edgeState2.getFlags(), iter2.detach(false).getFlags());
    assertEquals(edgeState3.getFlags(), iter2.detach(true).getFlags());
  }
  @Test
  public void testCreateDuplicateEdges() {
    graph = createGraph();
    graph.edge(2, 1, 12, true);
    graph.edge(2, 3, 12, true);
    graph.edge(2, 3, 13, false);
    assertEquals(3, GHUtility.count(carOutExplorer.setBaseNode(2)));

    // no exception
    graph.getEdgeProps(1, 3);

    // raise exception
    try {
      graph.getEdgeProps(4, 3);
      assertTrue(false);
    } catch (Exception ex) {
    }
    try {
      graph.getEdgeProps(-1, 3);
      assertTrue(false);
    } catch (Exception ex) {
    }

    EdgeIterator iter = carOutExplorer.setBaseNode(2);
    assertTrue(iter.next());
    EdgeIteratorState oneIter = graph.getEdgeProps(iter.getEdge(), 3);
    assertEquals(13, oneIter.getDistance(), 1e-6);
    assertEquals(2, oneIter.getBaseNode());
    assertTrue(carEncoder.isBool(oneIter.getFlags(), FlagEncoder.K_FORWARD));
    assertFalse(carEncoder.isBool(oneIter.getFlags(), FlagEncoder.K_BACKWARD));

    oneIter = graph.getEdgeProps(iter.getEdge(), 2);
    assertEquals(13, oneIter.getDistance(), 1e-6);
    assertEquals(3, oneIter.getBaseNode());
    assertFalse(carEncoder.isBool(oneIter.getFlags(), FlagEncoder.K_FORWARD));
    assertTrue(carEncoder.isBool(oneIter.getFlags(), FlagEncoder.K_BACKWARD));

    graph.edge(3, 2, 14, true);
    assertEquals(4, GHUtility.count(carOutExplorer.setBaseNode(2)));
  }
  @Test
  public void testEdgeProperties() {
    graph = createGraph();
    EdgeIteratorState iter1 = graph.edge(0, 1, 10, true);
    EdgeIteratorState iter2 = graph.edge(0, 2, 20, true);

    int edgeId = iter1.getEdge();
    EdgeIteratorState iter = graph.getEdgeProps(edgeId, 0);
    assertEquals(10, iter.getDistance(), 1e-5);

    edgeId = iter2.getEdge();
    iter = graph.getEdgeProps(edgeId, 0);
    assertEquals(2, iter.getBaseNode());
    assertEquals(0, iter.getAdjNode());
    assertEquals(20, iter.getDistance(), 1e-5);

    iter = graph.getEdgeProps(edgeId, 2);
    assertEquals(0, iter.getBaseNode());
    assertEquals(2, iter.getAdjNode());
    assertEquals(20, iter.getDistance(), 1e-5);

    iter = graph.getEdgeProps(edgeId, Integer.MIN_VALUE);
    assertFalse(iter == null);
    assertEquals(0, iter.getBaseNode());
    assertEquals(2, iter.getAdjNode());
    iter = graph.getEdgeProps(edgeId, 1);
    assertTrue(iter == null);

    // delete
    graph.markNodeRemoved(1);
    graph.optimize();

    // throw exception if accessing deleted edge
    try {
      graph.getEdgeProps(iter1.getEdge(), -1);
      assertTrue(false);
    } catch (Exception ex) {
    }
  }