@Test
  public void testCopy() {
    Graph g = initUnsorted(createGraph());
    EdgeIteratorState eb = g.edge(6, 5, 11, true);
    eb.setWayGeometry(Helper.createPointList(12, 10, -1, 3));
    LevelGraph lg = new GraphBuilder(encodingManager).levelGraphCreate();
    GHUtility.copyTo(g, lg);
    eb = lg.getEdgeProps(eb.getEdge(), 6);
    assertEquals(Helper.createPointList(-1, 3, 12, 10), eb.getWayGeometry());
    assertEquals(0, lg.getLevel(0));
    assertEquals(0, lg.getLevel(1));
    assertEquals(0, lg.getLatitude(0), 1e-6);
    assertEquals(1, lg.getLongitude(0), 1e-6);
    assertEquals(2.5, lg.getLatitude(1), 1e-6);
    assertEquals(4.5, lg.getLongitude(1), 1e-6);
    assertEquals(9, lg.getNodes());
    EdgeIterator iter = lg.createEdgeExplorer().setBaseNode(8);
    iter.next();
    assertEquals(2.05, iter.getDistance(), 1e-6);
    assertEquals("11", BitUtil.toBitString(iter.getFlags(), 2));
    iter.next();
    assertEquals(0.5, iter.getDistance(), 1e-6);
    assertEquals("11", BitUtil.toBitString(iter.getFlags(), 2));

    iter = lg.createEdgeExplorer().setBaseNode(7);
    iter.next();
    assertEquals(2.1, iter.getDistance(), 1e-6);
    assertEquals("01", BitUtil.toBitString(iter.getFlags(), 2));
    assertTrue(iter.next());
    assertEquals(0.7, iter.getDistance(), 1e-6);
  }
 @Test
 public void testInfinityWeight() {
   graph = createGraph();
   EdgeIteratorState edge = graph.edge(0, 1);
   edge.setDistance(Double.POSITIVE_INFINITY);
   assertTrue(Double.isInfinite(edge.getDistance()));
 }
  @Test
  public void internalDisconnect() {
    GraphHopperStorage storage = createGHStorage();
    BaseGraph graph = (BaseGraph) storage.getGraph(Graph.class);
    EdgeIteratorState iter0 = graph.edge(0, 1, 10, true);
    EdgeIteratorState iter2 = graph.edge(1, 2, 10, true);
    EdgeIteratorState iter3 = graph.edge(0, 3, 10, true);

    EdgeExplorer explorer = graph.createEdgeExplorer();

    assertEquals(GHUtility.asSet(3, 1), GHUtility.getNeighbors(explorer.setBaseNode(0)));
    assertEquals(GHUtility.asSet(2, 0), GHUtility.getNeighbors(explorer.setBaseNode(1)));
    // remove edge "1-2" but only from 1 not from 2
    graph.edgeAccess.internalEdgeDisconnect(
        iter2.getEdge(), -1, iter2.getBaseNode(), iter2.getAdjNode());
    assertEquals(GHUtility.asSet(0), GHUtility.getNeighbors(explorer.setBaseNode(1)));
    assertEquals(GHUtility.asSet(1), GHUtility.getNeighbors(explorer.setBaseNode(2)));
    // let 0 unchanged -> no side effects
    assertEquals(GHUtility.asSet(3, 1), GHUtility.getNeighbors(explorer.setBaseNode(0)));

    // remove edge "0-1" but only from 0
    graph.edgeAccess.internalEdgeDisconnect(
        iter0.getEdge(),
        (long) iter3.getEdge() * graph.edgeEntryBytes,
        iter0.getBaseNode(),
        iter0.getAdjNode());
    assertEquals(GHUtility.asSet(3), GHUtility.getNeighbors(explorer.setBaseNode(0)));
    assertEquals(GHUtility.asSet(0), GHUtility.getNeighbors(explorer.setBaseNode(3)));
    assertEquals(GHUtility.asSet(0), GHUtility.getNeighbors(explorer.setBaseNode(1)));
    storage.close();
  }
 @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 test8BytesFlags() {
    Directory dir = new RAMDirectory();
    List<FlagEncoder> list = new ArrayList<FlagEncoder>();
    list.add(new TmpCarFlagEncoder(29, 0.001));
    list.add(new TmpCarFlagEncoder(29, 0.001));
    EncodingManager manager = new EncodingManager(list, 8, 0);
    graph = new GraphHopperStorage(dir, manager, false).create(defaultSize);

    EdgeIteratorState edge = graph.edge(0, 1);
    edge.setFlags(Long.MAX_VALUE / 3);
    // System.out.println(BitUtil.LITTLE.toBitString(Long.MAX_VALUE / 3) + "\n" +
    // BitUtil.LITTLE.toBitString(edge.getFlags()));
    assertEquals(Long.MAX_VALUE / 3, edge.getFlags());
    graph.close();

    graph = new GraphHopperStorage(dir, manager, false).create(defaultSize);

    edge = graph.edge(0, 1);
    edge.setFlags(list.get(0).setProperties(99.123, true, true));
    assertEquals(99.123, list.get(0).getSpeed(edge.getFlags()), 1e-3);
    long flags = GHUtility.getEdge(graph, 1, 0).getFlags();
    assertEquals(99.123, list.get(0).getSpeed(flags), 1e-3);
    assertTrue(list.get(0).isBool(flags, FlagEncoder.K_FORWARD));
    assertTrue(list.get(0).isBool(flags, FlagEncoder.K_BACKWARD));
    edge = graph.edge(2, 3);
    edge.setFlags(list.get(1).setProperties(44.123, true, false));
    assertEquals(44.123, list.get(1).getSpeed(edge.getFlags()), 1e-3);
    flags = GHUtility.getEdge(graph, 3, 2).getFlags();
    assertEquals(44.123, list.get(1).getSpeed(flags), 1e-3);
    assertTrue(list.get(1).isBool(flags, FlagEncoder.K_FORWARD));
    assertFalse(list.get(1).isBool(flags, FlagEncoder.K_BACKWARD));
  }
  @Test
  public void testNameIndex() {
    graph = createGraph();
    EdgeIteratorState iter1 = graph.edge(0, 1, 10, true);
    iter1.setName("named street1");

    EdgeIteratorState iter2 = graph.edge(0, 1, 10, true);
    iter2.setName("named street2");

    assertEquals(
        "named street1", graph.getEdgeProps(iter1.getEdge(), iter1.getAdjNode()).getName());
    assertEquals(
        "named street2", graph.getEdgeProps(iter2.getEdge(), iter2.getAdjNode()).getName());
  }
  @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());
  }
  protected void checkGraph(Graph g) {
    NodeAccess na = g.getNodeAccess();
    assertTrue(na.is3D());
    assertTrue(g.getBounds().isValid());

    assertEquals(new BBox(10, 20, 10, 12, 0, 1), g.getBounds());
    assertEquals(10, na.getLatitude(0), 1e-2);
    assertEquals(10, na.getLongitude(0), 1e-2);
    EdgeExplorer explorer = g.createEdgeExplorer(carOutFilter);
    assertEquals(2, GHUtility.count(explorer.setBaseNode(0)));
    assertEquals(GHUtility.asSet(2, 1), GHUtility.getNeighbors(explorer.setBaseNode(0)));

    EdgeIterator iter = explorer.setBaseNode(0);
    assertTrue(iter.next());
    assertEquals(Helper.createPointList3D(3.5, 4.5, 0, 5, 6, 0), iter.fetchWayGeometry(0));

    assertTrue(iter.next());
    assertEquals(Helper.createPointList3D(1.5, 1, 0, 2, 3, 0), iter.fetchWayGeometry(0));
    assertEquals(Helper.createPointList3D(10, 10, 0, 1.5, 1, 0, 2, 3, 0), iter.fetchWayGeometry(1));
    assertEquals(Helper.createPointList3D(1.5, 1, 0, 2, 3, 0, 11, 20, 1), iter.fetchWayGeometry(2));

    assertEquals(11, na.getLatitude(1), 1e-2);
    assertEquals(20, na.getLongitude(1), 1e-2);
    assertEquals(2, GHUtility.count(explorer.setBaseNode(1)));
    assertEquals(GHUtility.asSet(2, 0), GHUtility.getNeighbors(explorer.setBaseNode(1)));

    assertEquals(12, na.getLatitude(2), 1e-2);
    assertEquals(12, na.getLongitude(2), 1e-2);
    assertEquals(1, GHUtility.count(explorer.setBaseNode(2)));

    assertEquals(GHUtility.asSet(0), GHUtility.getNeighbors(explorer.setBaseNode(2)));

    EdgeIteratorState eib = GHUtility.getEdge(g, 1, 2);
    assertEquals(Helper.createPointList3D(), eib.fetchWayGeometry(0));
    assertEquals(Helper.createPointList3D(11, 20, 1), eib.fetchWayGeometry(1));
    assertEquals(Helper.createPointList3D(12, 12, 0.4), eib.fetchWayGeometry(2));
    assertEquals(GHUtility.asSet(0), GHUtility.getNeighbors(explorer.setBaseNode(2)));
  }
  @Test
  public void testSave_and_fileFormat() throws IOException {
    graph = newGHStorage(new RAMDirectory(defaultGraphLoc, true), true).create(defaultSize);
    NodeAccess na = graph.getNodeAccess();
    assertTrue(na.is3D());
    na.setNode(0, 10, 10, 0);
    na.setNode(1, 11, 20, 1);
    na.setNode(2, 12, 12, 0.4);

    EdgeIteratorState iter2 = graph.edge(0, 1, 100, true);
    iter2.setWayGeometry(Helper.createPointList3D(1.5, 1, 0, 2, 3, 0));
    EdgeIteratorState iter1 = graph.edge(0, 2, 200, true);
    iter1.setWayGeometry(Helper.createPointList3D(3.5, 4.5, 0, 5, 6, 0));
    graph.edge(9, 10, 200, true);
    graph.edge(9, 11, 200, true);
    graph.edge(1, 2, 120, false);

    iter1.setName("named street1");
    iter2.setName("named street2");

    checkGraph(graph);
    graph.flush();
    graph.close();

    graph = newGHStorage(new MMapDirectory(defaultGraphLoc), true);
    assertTrue(graph.loadExisting());

    assertEquals(12, graph.getNodes());
    checkGraph(graph);

    assertEquals(
        "named street1", graph.getEdgeIteratorState(iter1.getEdge(), iter1.getAdjNode()).getName());
    assertEquals(
        "named street2", graph.getEdgeIteratorState(iter2.getEdge(), iter2.getAdjNode()).getName());
    graph.edge(3, 4, 123, true).setWayGeometry(Helper.createPointList3D(4.4, 5.5, 0, 6.6, 7.7, 0));
    checkGraph(graph);
  }
  @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) {
    }
  }
  @Test
  public void testCopyProperties() {
    graph = createGraph();
    EdgeIteratorState edge =
        graph.edge(1, 3, 10, false).setName("testing").setWayGeometry(Helper.createPointList(1, 2));

    EdgeIteratorState newEdge = graph.edge(1, 3, 10, false);
    edge.copyPropertiesTo(newEdge);
    assertEquals(edge.getName(), newEdge.getName());
    assertEquals(edge.getDistance(), newEdge.getDistance(), 1e-7);
    assertEquals(edge.getFlags(), newEdge.getFlags());
    assertEquals(edge.fetchWayGeometry(0), newEdge.fetchWayGeometry(0));
  }
  @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());
  }
  public void testAdditionalEdgeField() {
    GraphExtension extStorage =
        new GraphExtension() {
          @Override
          public boolean isRequireNodeField() {
            return false;
          }

          @Override
          public boolean isRequireEdgeField() {
            return true;
          }

          @Override
          public int getDefaultNodeFieldValue() {
            throw new UnsupportedOperationException("Not supported.");
          }

          @Override
          public int getDefaultEdgeFieldValue() {
            return 2;
          }

          @Override
          public void init(Graph graph, Directory dir) {}

          @Override
          public void setSegmentSize(int bytes) {}

          @Override
          public GraphExtension copyTo(GraphExtension extStorage) {
            return this;
          }

          @Override
          public boolean loadExisting() {
            return true;
          }

          @Override
          public GraphExtension create(long byteCount) {
            return this;
          }

          @Override
          public void flush() {}

          @Override
          public void close() {}

          @Override
          public boolean isClosed() {
            return false;
          }

          @Override
          public long getCapacity() {
            return 0;
          }
        };

    GraphHopperStorage storage =
        new GraphHopperStorage(new RAMDirectory(), encodingManager, false, extStorage);
    storage.create(1000);
    EdgeIteratorState iter = storage.edge(0, 1, 10, true);

    assertEquals(extStorage.getDefaultEdgeFieldValue(), iter.getAdditionalField());
  }