package de.westnordost.streetcomplete.data.osm.tql;
import junit.framework.TestCase;
import de.westnordost.osmapi.map.data.BoundingBox;
/** Integration test for the filter parser and the filter expression, the whole way from parsing
* the tag filters expression to returning it as a OQL string. More convenient this way since the
* easiest way to create a filter expresssion is to parse it from string. */
public class FiltersParserTest extends TestCase
{
public void testNode()
{
check("nodes", "node;out meta geom;");
check("NODES", "node;out meta geom;");
}
public void testWay()
{
check("ways", "way;out meta geom;");
check("WAYS", "way;out meta geom;");
}
public void testRelation()
{
check("relations", "rel;out meta geom;");
check("RELATIONS", "rel;out meta geom;");
}
public void testMultipleElementTypes()
{
check("nodes, ways, relations", "(node;way;rel;);out meta geom;");
check("nodes ,ways", "(node;way;);out meta geom;");
check("nodes , ways", "(node;way;);out meta geom;");
}
public void testAnyQuote()
{
check("nodes with 'shop'", "node['shop'];out meta geom;");
check("nodes with \"shop\"", "node[\"shop\"];out meta geom;");
check("nodes with \"shoppin'\"", "node[\"shoppin'\"];out meta geom;");
check("nodes with '\"shop\"ping'", "node['\"shop\"ping'];out meta geom;");
}
public void testMultipleElementTypesWithTag()
{
check("nodes, ways, relations with shop",
"(node[\"shop\"];way[\"shop\"];rel[\"shop\"];);out meta geom;");
}
public void testWhitespaceInFrontOkay()
{
check("\t\n nodes", "node;out meta geom;");
}
public void testFailIfNoElementDeclarationInFront()
{
shouldFail("butter");
}
public void testFailIfElementDeclarationInFrontDuplicate()
{
shouldFail("nodes, nodes");
}
public void testFailIfElementDeclarationInFrontAnyInvalid()
{
shouldFail("nodes, butter");
}
public void testTagNoSeparator()
{
shouldFail("nodeswith");
shouldFail("nodes withhighway");
}
public void testTagKeyLikeReservedWord()
{
shouldFail("nodes with with");
shouldFail("nodes with around");
shouldFail("nodes with or");
shouldFail("nodes with and");
}
public void testTagKeyLikeReservedWordWithQuotationMarks()
{
check("nodes with \"with\"", "node[\"with\"];out meta geom;");
check("nodes with \"with\"=\"with\"", "node[\"with\"=\"with\"];out meta geom;");
}
public void testTagKeyWithQuotationMarks()
{
check("nodes with \"highway = residential or bla\"",
"node[\"highway = residential or bla\"];out meta geom;");
}
public void testTagValueWithQuotationMarks()
{
check("nodes with highway = \"residential or bla\"",
"node[\"highway\"=\"residential or bla\"];out meta geom;");
}
public void testTagValueGarbage()
{
check("nodes with highway = §$%&%/??",
"node[\"highway\"=\"§$%&%/??\"];out meta geom;");
}
public void testTagKeyQuotationMarksNotClosed()
{
shouldFail("nodes with \"highway = residential or bla");
}
public void testTagValueQuotationMarksNotClosed()
{
shouldFail("nodes with highway = \"residential or bla");
}
public void testTagKey()
{
String expect = "node[\"highway\"];out meta geom;";
check("nodes with highway", expect);
check("nodes with(highway)", expect);
check("nodes with (highway)", expect);
check("nodes with ( highway)", expect);
check("nodes with( highway)", expect);
check("nodes with(highway )", expect);
check("nodes with(highway ) ", expect);
check("nodes with(highway) ", expect);
}
public void testDanglingOp()
{
shouldFail("nodes with highway=");
}
public void testDanglingBoolOp()
{
shouldFail("nodes with highway and");
shouldFail("nodes with highway or ");
}
public void testBracketNotClosed()
{
shouldFail("nodes with (highway");
}
public void testBracketClosedTooOften()
{
shouldFail("nodes with highway)");
}
public void testUnknownThingAfterTag()
{
shouldFail("nodes with highway what is this");
}
public void testTagNegation()
{
check("nodes with !highway", "node[\"highway\"!~\".\"];out meta geom;");
}
public void testTagOperatorWhitespaces()
{
String expect = "node[\"highway\"=\"residential\"];out meta geom;";
check("nodes with highway=residential", expect);
check("nodes with highway =residential", expect);
check("nodes with highway= residential", expect);
check("nodes with highway = residential", expect);
}
public void testTagOperator()
{
check("nodes with highway=residential", "node[\"highway\"=\"residential\"];out meta geom;");
check("nodes with highway!=residential", "node[\"highway\"!=\"residential\"];out meta geom;");
check("nodes with highway~residential", "node[\"highway\"~\"^(residential)$\"];out meta geom;");
check("nodes with highway!~residential", "node[\"highway\"!~\"^(residential)$\"];out meta geom;");
}
public void testTagNegationNotCombinableWithOperator()
{
shouldFail("nodes with !highway=residential");
shouldFail("nodes with !highway!=residential");
shouldFail("nodes with !highway~residential");
shouldFail("nodes with !highway!~residential");
}
public void testTwoTags()
{
check("nodes with highway and name", "node[\"highway\"][\"name\"];out meta geom;");
check("nodes with highway or name", "(node[\"highway\"];node[\"name\"];);out meta geom;");
}
public void testOrInAnd()
{
check("nodes with(highway or railway)and name",
"(node[\"highway\"][\"name\"];node[\"railway\"][\"name\"];);out meta geom;");
}
public void testBoundingBox()
{
BoundingBox bbox = new BoundingBox(0,0,5,10);
check("nodes", "[bbox:0.0,0.0,5.0,10.0];node;out meta geom;", bbox);
check("nodes with highway", "[bbox:0.0,0.0,5.0,10.0];node[\"highway\"];out meta geom;", bbox);
check("nodes with highway or railway",
"[bbox:0.0,0.0,5.0,10.0];(node[\"highway\"];node[\"railway\"];);out meta geom;", bbox);
}
public void testBoundingBoxWithMultipleElementTypes()
{
BoundingBox bbox = new BoundingBox(0,0,5,10);
check("nodes, ways, relations", "[bbox:0.0,0.0,5.0,10.0];(node;way;rel;);out meta geom;", bbox);
check("nodes, ways, relations with highway",
"[bbox:0.0,0.0,5.0,10.0];(" +
"node[\"highway\"];" +
"way[\"highway\"];" +
"rel[\"highway\"];" +
");" +
"out meta geom;", bbox);
check("nodes, ways, relations with highway or railway",
"[bbox:0.0,0.0,5.0,10.0];(" +
"node[\"highway\"];" +
"node[\"railway\"];" +
"way[\"highway\"];" +
"way[\"railway\"];" +
"rel[\"highway\"];" +
"rel[\"railway\"];" +
");" +
"out meta geom;", bbox);
}
private void shouldFail(String input)
{
try
{
new FiltersParser().parse(input);
fail();
}
catch(RuntimeException e) {}
}
private void check(String input, String output)
{
check(input, output, null);
}
private void check(String input, String output, BoundingBox bbox)
{
TagFilterExpression expr = new FiltersParser().parse(input);
assertEquals(output, expr.toOverpassQLString(bbox));
}
}