/* * Licensed to GraphHopper GmbH under one or more contributor * license agreements. See the NOTICE file distributed with this work for * additional information regarding copyright ownership. * * GraphHopper GmbH licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.graphhopper; import com.graphhopper.json.geo.JsonFeature; import com.graphhopper.routing.util.EncodingManager; import com.graphhopper.storage.Graph; import com.graphhopper.storage.GraphBuilder; import com.graphhopper.storage.GraphHopperStorage; import com.graphhopper.storage.NodeAccess; import com.graphhopper.storage.change.ChangeGraphHelper; import com.graphhopper.storage.index.LocationIndex; import com.graphhopper.util.PointList; import com.graphhopper.util.shapes.BBox; import org.junit.Test; import java.util.*; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import static org.junit.Assert.*; /** * @author Peter Karich */ public class GraphHopperAPITest { final EncodingManager encodingManager = new EncodingManager("car"); void initGraph(GraphHopperStorage graph) { NodeAccess na = graph.getNodeAccess(); na.setNode(0, 42, 10); na.setNode(1, 42.1, 10.1); na.setNode(2, 42.1, 10.2); na.setNode(3, 42, 10.4); graph.edge(0, 1, 10, true); graph.edge(2, 3, 10, true); } @Test public void testLoad() { GraphHopperStorage graph = new GraphBuilder(encodingManager).create(); initGraph(graph); // do further changes: NodeAccess na = graph.getNodeAccess(); na.setNode(4, 41.9, 10.2); graph.edge(1, 2, 10, false); graph.edge(0, 4, 40, true); graph.edge(4, 3, 40, true); GraphHopper instance = new GraphHopper(). setStoreOnFlush(false). setEncodingManager(encodingManager).setCHEnabled(false). loadGraph(graph); // 3 -> 0 GHResponse rsp = instance.route(new GHRequest(42, 10.4, 42, 10)); assertFalse(rsp.hasErrors()); PathWrapper arsp = rsp.getBest(); assertEquals(80, arsp.getDistance(), 1e-6); PointList points = arsp.getPoints(); assertEquals(42, points.getLatitude(0), 1e-5); assertEquals(10.4, points.getLongitude(0), 1e-5); assertEquals(41.9, points.getLatitude(1), 1e-5); assertEquals(10.2, points.getLongitude(1), 1e-5); assertEquals(3, points.getSize()); instance.close(); } @Test public void testDisconnected179() { GraphHopperStorage graph = new GraphBuilder(encodingManager).create(); initGraph(graph); GraphHopper instance = new GraphHopper(). setStoreOnFlush(false). setEncodingManager(encodingManager).setCHEnabled(false). loadGraph(graph); GHResponse rsp = instance.route(new GHRequest(42, 10, 42, 10.4)); assertTrue(rsp.hasErrors()); try { rsp.getBest().getPoints(); assertTrue(false); } catch (Exception ex) { } instance.close(); } @Test public void testNoLoad() { GraphHopper instance = new GraphHopper(). setStoreOnFlush(false). setEncodingManager(encodingManager).setCHEnabled(false); try { instance.route(new GHRequest(42, 10.4, 42, 10)); assertTrue(false); } catch (Exception ex) { assertTrue(ex.getMessage(), ex.getMessage().startsWith("Do a successful call to load or importOrLoad before routing")); } instance = new GraphHopper().setEncodingManager(encodingManager); try { instance.route(new GHRequest(42, 10.4, 42, 10)); assertTrue(false); } catch (Exception ex) { assertTrue(ex.getMessage(), ex.getMessage().startsWith("Do a successful call to load or importOrLoad before routing")); } } @Test public void testConcurrentGraphChange() throws InterruptedException { final GraphHopperStorage graph = new GraphBuilder(encodingManager).create(); initGraph(graph); graph.edge(1, 2, 10, true); final CountDownLatch latch = new CountDownLatch(1); final AtomicInteger checkPointCounter = new AtomicInteger(0); final GraphHopper graphHopper = new GraphHopper() { @Override protected ChangeGraphHelper createChangeGraphHelper(Graph graph, LocationIndex locationIndex) { return new ChangeGraphHelper(graph, locationIndex) { @Override public long applyChanges(EncodingManager em, Collection<JsonFeature> features) { // force sleep inside the lock and let the main thread run until the lock barrier latch.countDown(); try { Thread.sleep(400); } catch (InterruptedException e) { throw new RuntimeException(e); } checkPointCounter.incrementAndGet(); return super.applyChanges(em, features); } }; } }.setStoreOnFlush(false).setEncodingManager(encodingManager).setCHEnabled(false). loadGraph(graph); GHResponse rsp = graphHopper.route(new GHRequest(42, 10.4, 42, 10)); assertFalse(rsp.toString(), rsp.hasErrors()); assertEquals(1800, rsp.getBest().getTime()); final List<JsonFeature> list = new ArrayList<>(); Map<String, Object> properties = new HashMap<>(); properties.put("speed", 5); list.add(new JsonFeature("1", "bbox", new BBox(10.399, 10.4, 42.0, 42.001), null, properties)); ExecutorService executorService = Executors.newFixedThreadPool(1); executorService.submit(new Runnable() { @Override public void run() { graphHopper.changeGraph(list); checkPointCounter.incrementAndGet(); } }); latch.await(); assertEquals(0, checkPointCounter.get()); rsp = graphHopper.route(new GHRequest(42, 10.4, 42, 10)); assertFalse(rsp.toString(), rsp.hasErrors()); assertEquals(8400, rsp.getBest().getTime()); executorService.shutdown(); executorService.awaitTermination(3, TimeUnit.SECONDS); assertEquals(2, checkPointCounter.get()); } }