/*
* 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.routing.util;
import com.graphhopper.reader.ReaderRelation;
import com.graphhopper.reader.ReaderWay;
import com.graphhopper.routing.weighting.PriorityWeighting;
import com.graphhopper.util.BitUtil;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.junit.Assert.*;
/**
* @author Peter Karich
*/
public class EncodingManagerTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testCompatibility() {
EncodingManager manager = new EncodingManager("car,bike,foot");
BikeFlagEncoder bike = (BikeFlagEncoder) manager.getEncoder("bike");
CarFlagEncoder car = (CarFlagEncoder) manager.getEncoder("car");
FootFlagEncoder foot = (FootFlagEncoder) manager.getEncoder("foot");
assertNotEquals(car, bike);
assertNotEquals(car, foot);
assertNotEquals(car.hashCode(), bike.hashCode());
assertNotEquals(car.hashCode(), foot.hashCode());
FootFlagEncoder foot2 = new FootFlagEncoder();
EncodingManager manager2 = new EncodingManager(foot2);
assertNotEquals(foot, foot2);
assertNotEquals(foot.hashCode(), foot2.hashCode());
FootFlagEncoder foot3 = new FootFlagEncoder();
EncodingManager manager3 = new EncodingManager(foot3);
assertEquals(foot3, foot2);
assertEquals(foot3.hashCode(), foot2.hashCode());
try {
new EncodingManager("car,car");
assertTrue("do not allow duplicate flag encoders", false);
} catch (Exception ex) {
}
}
@Test
public void testEncoderAcceptNoException() {
EncodingManager manager = new EncodingManager("car");
assertTrue(manager.supports("car"));
assertFalse(manager.supports("foot"));
}
@Test
public void testEncoderWithWrongVersionIsRejected() {
thrown.expect(IllegalArgumentException.class);
EncodingManager manager = new EncodingManager("car|version=0");
}
@Test
public void testWrongEncoders() {
try {
FootFlagEncoder foot = new FootFlagEncoder();
new EncodingManager(foot, foot);
assertTrue(false);
} catch (Exception ex) {
assertEquals("You must not register a FlagEncoder (foot) twice!", ex.getMessage());
}
try {
new EncodingManager(new FootFlagEncoder(), new CarFlagEncoder(), new BikeFlagEncoder(), new MountainBikeFlagEncoder(), new RacingBikeFlagEncoder());
assertTrue(false);
} catch (Exception ex) {
assertTrue(ex.getMessage(), ex.getMessage().startsWith("Encoders are requesting 44 bits, more than 32 bits of way flags. Decrease the"));
}
}
@Test
public void testToDetailsStringIncludesEncoderVersionNumber() {
FlagEncoder encoder = new AbstractFlagEncoder(1, 2.0, 3) {
@Override
public int getVersion() {
return 10;
}
@Override
public String toString() {
return "new_encoder";
}
@Override
protected String getPropertiesString() {
return "my_properties";
}
@Override
public long handleRelationTags(ReaderRelation relation, long oldRelationFlags) {
return 0;
}
@Override
public long acceptWay(ReaderWay way) {
return 0;
}
@Override
public long handleWayTags(ReaderWay way, long allowed, long relationFlags) {
return 0;
}
};
EncodingManager subject = new EncodingManager(encoder);
assertEquals("new_encoder|my_properties|version=10", subject.toDetailsString());
}
@Test
public void testCombineRelations() {
ReaderWay osmWay = new ReaderWay(1);
osmWay.setTag("highway", "track");
ReaderRelation osmRel = new ReaderRelation(1);
BikeFlagEncoder defaultBike = new BikeFlagEncoder();
BikeFlagEncoder lessRelationCodes = new BikeFlagEncoder() {
@Override
public int defineRelationBits(int index, int shift) {
relationCodeEncoder = new EncodedValue("RelationCode2", shift, 2, 1, 0, 3);
return shift + 2;
}
@Override
public long handleRelationTags(ReaderRelation relation, long oldRelFlags) {
if (relation.hasTag("route", "bicycle"))
return relationCodeEncoder.setValue(0, 2);
return relationCodeEncoder.setValue(0, 0);
}
@Override
protected int handlePriority(ReaderWay way, double wayTypeSpeed, int priorityFromRelation) {
return priorityFromRelation;
}
@Override
public String toString() {
return "less_relations_bits";
}
};
EncodingManager manager = new EncodingManager(defaultBike, lessRelationCodes);
// relation code is PREFER
osmRel.setTag("route", "bicycle");
osmRel.setTag("network", "lcn");
long relFlags = manager.handleRelationTags(osmRel, 0);
long allow = defaultBike.acceptBit | lessRelationCodes.acceptBit;
long flags = manager.handleWayTags(osmWay, allow, relFlags);
assertTrue(defaultBike.getDouble(flags, PriorityWeighting.KEY)
> lessRelationCodes.getDouble(flags, PriorityWeighting.KEY));
}
@Test
public void testMixBikeTypesAndRelationCombination() {
ReaderWay osmWay = new ReaderWay(1);
osmWay.setTag("highway", "track");
osmWay.setTag("tracktype", "grade1");
ReaderRelation osmRel = new ReaderRelation(1);
BikeFlagEncoder bikeEncoder = new BikeFlagEncoder();
MountainBikeFlagEncoder mtbEncoder = new MountainBikeFlagEncoder();
EncodingManager manager = new EncodingManager(bikeEncoder, mtbEncoder);
// relation code for network rcn is VERY_NICE for bike and PREFER for mountainbike
osmRel.setTag("route", "bicycle");
osmRel.setTag("network", "rcn");
long relFlags = manager.handleRelationTags(osmRel, 0);
long allow = bikeEncoder.acceptBit | mtbEncoder.acceptBit;
long flags = manager.handleWayTags(osmWay, allow, relFlags);
// bike: uninfluenced speed for grade but via network => VERY_NICE
// mtb: uninfluenced speed only PREFER
assertTrue(bikeEncoder.getDouble(flags, PriorityWeighting.KEY)
> mtbEncoder.getDouble(flags, PriorityWeighting.KEY));
}
public void testFullBitMask() {
BitUtil bitUtil = BitUtil.LITTLE;
EncodingManager manager = new EncodingManager("car,foot");
AbstractFlagEncoder carr = (AbstractFlagEncoder) manager.getEncoder("car");
assertTrue(bitUtil.toBitString(carr.getNodeBitMask()).endsWith("00000000001111111"));
AbstractFlagEncoder foot = (AbstractFlagEncoder) manager.getEncoder("foot");
assertTrue(bitUtil.toBitString(foot.getNodeBitMask()).endsWith("00011111110000000"));
}
@Test
public void testFixWayName() {
assertEquals("B8, B12", EncodingManager.fixWayName("B8;B12"));
assertEquals("B8, B12", EncodingManager.fixWayName("B8; B12"));
}
@Test
public void testCompatibilityBug() {
EncodingManager manager2 = new EncodingManager(FlagEncoderFactory.DEFAULT, "bike2", 8);
ReaderWay osmWay = new ReaderWay(1);
osmWay.setTag("highway", "footway");
osmWay.setTag("name", "test");
BikeFlagEncoder singleBikeEnc = (BikeFlagEncoder) manager2.getEncoder("bike2");
long flags = manager2.handleWayTags(osmWay, singleBikeEnc.acceptBit, 0);
double singleSpeed = singleBikeEnc.getSpeed(flags);
assertEquals(4, singleSpeed, 1e-3);
assertEquals(singleSpeed, singleBikeEnc.getReverseSpeed(flags), 1e-3);
EncodingManager manager = new EncodingManager(FlagEncoderFactory.DEFAULT, "bike2,bike,foot", 8);
FootFlagEncoder foot = (FootFlagEncoder) manager.getEncoder("foot");
BikeFlagEncoder bike = (BikeFlagEncoder) manager.getEncoder("bike2");
long acceptBits = foot.acceptBit | bike.acceptBit;
flags = manager.handleWayTags(osmWay, acceptBits, 0);
assertEquals(singleSpeed, bike.getSpeed(flags), 1e-2);
assertEquals(singleSpeed, bike.getReverseSpeed(flags), 1e-2);
assertEquals(5, foot.getSpeed(flags), 1e-2);
assertEquals(5, foot.getReverseSpeed(flags), 1e-2);
}
@Test
public void testSupportFords() {
// 1) no encoder crossing fords
String flagEncodersStr = "car,bike,foot";
EncodingManager manager = new EncodingManager(FlagEncoderFactory.DEFAULT, flagEncodersStr, 8);
assertTrue(((AbstractFlagEncoder) manager.getEncoder("car")).isBlockFords());
assertTrue(((AbstractFlagEncoder) manager.getEncoder("bike")).isBlockFords());
assertTrue(((AbstractFlagEncoder) manager.getEncoder("foot")).isBlockFords());
// 2) two encoders crossing fords
flagEncodersStr = "car,bike|block_fords=false,foot|block_fords=false";
manager = new EncodingManager(FlagEncoderFactory.DEFAULT, flagEncodersStr, 8);
assertTrue(((AbstractFlagEncoder) manager.getEncoder("car")).isBlockFords());
assertFalse(((AbstractFlagEncoder) manager.getEncoder("bike")).isBlockFords());
assertFalse(((AbstractFlagEncoder) manager.getEncoder("foot")).isBlockFords());
// 2) Try combined with another tag
flagEncodersStr = "car|turn_costs=true|block_fords=true,bike,foot|block_fords=false";
manager = new EncodingManager(FlagEncoderFactory.DEFAULT, flagEncodersStr, 8);
assertTrue(((AbstractFlagEncoder) manager.getEncoder("car")).isBlockFords());
assertTrue(((AbstractFlagEncoder) manager.getEncoder("bike")).isBlockFords());
assertFalse(((AbstractFlagEncoder) manager.getEncoder("foot")).isBlockFords());
}
}