forked from planetfederal/geotools
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
implements the ATS conformance testsuite
See geoserver/geoserver-ogcapi#10 for the motivation.
- Loading branch information
Showing
6 changed files
with
909 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
...ted/cql2-text/src/test/java/org/geotools/filter/text/cql_2/conformance/ATSOnlineTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package org.geotools.filter.text.cql_2.conformance; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.net.URL; | ||
import java.nio.file.Path; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.TimeZone; | ||
import org.apache.commons.io.FileUtils; | ||
import org.geotools.api.data.DataStore; | ||
import org.geotools.api.data.DataStoreFinder; | ||
import org.geotools.http.HTTPResponse; | ||
import org.geotools.http.SimpleHttpClient; | ||
import org.junit.BeforeClass; | ||
|
||
/** | ||
* Base class for tests issued from the Abstract Test Suite (ATS). See | ||
* https://docs.ogc.org/is/21-065r2/21-065r2.html#ats for the context. | ||
* | ||
* <p>This class will download the official Natural Earth dataset and store it into the default | ||
* temporary directory. | ||
*/ | ||
public abstract class ATSOnlineTest { | ||
|
||
private static String NE_DATA_URL = | ||
"https://github.com/opengeospatial/ogcapi-features/raw/refs/heads/master/cql2/standard/data/ne110m4cql2.gpkg"; | ||
|
||
protected final File neGpkg = Path.of(System.getProperty("java.io.tmpdir"), "ne.gpkg").toFile(); | ||
|
||
@BeforeClass | ||
public static void forceGMT() { | ||
TimeZone.setDefault(TimeZone.getTimeZone("GMT")); | ||
} | ||
|
||
private void downloadNaturalEarthData() throws IOException { | ||
if (neGpkg.exists()) { | ||
return; | ||
} | ||
neGpkg.createNewFile(); | ||
SimpleHttpClient client = new SimpleHttpClient(); | ||
HTTPResponse r = client.get(new URL(NE_DATA_URL)); | ||
FileUtils.copyInputStreamToFile(r.getResponseStream(), neGpkg); | ||
} | ||
|
||
protected DataStore naturalEarthData() throws IOException { | ||
downloadNaturalEarthData(); | ||
Map params = new HashMap(); | ||
params.put("dbtype", "geopkg"); | ||
params.put("database", neGpkg.getAbsolutePath()); | ||
params.put("read-only", true); | ||
|
||
DataStore datastore = DataStoreFinder.getDataStore(params); | ||
|
||
return datastore; | ||
} | ||
} |
65 changes: 65 additions & 0 deletions
65
...src/test/java/org/geotools/filter/text/cql_2/conformance/ConformanceTest13OnlineTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package org.geotools.filter.text.cql_2.conformance; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
|
||
import java.io.IOException; | ||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import org.geootols.filter.text.cql_2.CQL2; | ||
import org.geotools.api.data.DataStore; | ||
import org.geotools.api.filter.Filter; | ||
import org.geotools.filter.text.cql2.CQLException; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
import org.junit.runners.Parameterized; | ||
|
||
/** See table 9 from section A.4.4 Conformance test 13. */ | ||
@RunWith(Parameterized.class) | ||
public class ConformanceTest13OnlineTest extends ATSOnlineTest { | ||
|
||
private final String criteria; | ||
private final int expectedFeatures; | ||
|
||
public ConformanceTest13OnlineTest(String criteria, int expectedFeatures) { | ||
this.criteria = criteria; | ||
this.expectedFeatures = expectedFeatures; | ||
} | ||
|
||
@Parameterized.Parameters(name = "{index} {0}") | ||
public static Collection<Object[]> params() { | ||
return Arrays.asList( | ||
new Object[][] { | ||
{"name LIKE 'B_r%'", 3}, | ||
{"name NOT LIKE 'B_r%'", 240}, | ||
{"pop_other between 1000000 and 3000000", 75}, | ||
{"pop_other not between 1000000 and 3000000", 168}, | ||
{"name IN ('Kiev','kobenhavn','Berlin','athens','foo')", 2}, | ||
{"name NOT IN ('Kiev','kobenhavn','Berlin','athens','foo')", 241}, | ||
{"pop_other in (1038288,1611692,3013258,3013257,3013259)", 3}, | ||
{"pop_other not in (1038288,1611692,3013258,3013257,3013259)", 240}, | ||
{"\"date\" in (DATE('2021-04-16'),DATE('2022-04-16'),DATE('2022-04-18'))", 2}, | ||
{ | ||
"\"date\" not in (DATE('2021-04-16'),DATE('2022-04-16'),DATE('2022-04-18'))", | ||
1 | ||
}, | ||
{"start in (TIMESTAMP('2022-04-16T10:13:19Z'))", 1}, | ||
{"start not in (TIMESTAMP('2022-04-16T10:13:19Z'))", 2}, | ||
{"boolean in (true)", 2}, | ||
{"boolean not in (false)", 2} | ||
}); | ||
} | ||
|
||
public @Test void testConformance() throws IOException, CQLException { | ||
DataStore ds = naturalEarthData(); | ||
int feat = featuresReturned(ds); | ||
ds.dispose(); | ||
|
||
assertEquals(this.expectedFeatures, feat); | ||
} | ||
|
||
private int featuresReturned(DataStore ds) throws CQLException, IOException { | ||
Filter filter = CQL2.toFilter(this.criteria); | ||
|
||
return ds.getFeatureSource("ne_110m_populated_places_simple").getFeatures(filter).size(); | ||
} | ||
} |
69 changes: 69 additions & 0 deletions
69
...src/test/java/org/geotools/filter/text/cql_2/conformance/ConformanceTest26OnlineTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package org.geotools.filter.text.cql_2.conformance; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
|
||
import java.io.IOException; | ||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import org.geootols.filter.text.cql_2.CQL2; | ||
import org.geotools.api.data.DataStore; | ||
import org.geotools.api.filter.Filter; | ||
import org.geotools.filter.text.cql2.CQLException; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
import org.junit.runners.Parameterized; | ||
|
||
/** See table 12 from section A.7.2 Conformance test 26. */ | ||
@RunWith(Parameterized.class) | ||
public class ConformanceTest26OnlineTest extends ATSOnlineTest { | ||
|
||
private final String dataset; | ||
private final String criteria; | ||
private final int expectedFeatures; | ||
|
||
public ConformanceTest26OnlineTest(String dataset, String criteria, int expectedFeatures) { | ||
this.dataset = dataset; | ||
this.criteria = criteria; | ||
this.expectedFeatures = expectedFeatures; | ||
} | ||
|
||
@Parameterized.Parameters(name = "{index} {0} {1}") | ||
public static Collection<Object[]> params() { | ||
return Arrays.asList( | ||
new Object[][] { | ||
{"ne_110m_admin_0_countries", "S_INTERSECTS(geom,BBOX(0,40,10,50))", 8}, | ||
{"ne_110m_admin_0_countries", "S_INTERSECTS(geom,BBOX(150,-90,-150,90))", 10}, | ||
{"ne_110m_admin_0_countries", "S_INTERSECTS(geom,POINT(7.02 49.92))", 1}, | ||
{ | ||
"ne_110m_admin_0_countries", | ||
"S_INTERSECTS(geom,BBOX(0,40,10,50)) and S_INTERSECTS(geom,BBOX(5,50,10,60))", | ||
3 | ||
}, | ||
{ | ||
"ne_110m_admin_0_countries", | ||
"S_INTERSECTS(geom,BBOX(0,40,10,50)) and not S_INTERSECTS(geom,BBOX(5,50,10,60))", | ||
5 | ||
}, | ||
{ | ||
"ne_110m_admin_0_countries", | ||
"S_INTERSECTS(geom,BBOX(0,40,10,50)) or S_INTERSECTS(geom,BBOX(-90,40,-60,50))", | ||
10 | ||
}, | ||
{"ne_110m_populated_places_simple", "S_INTERSECTS(geom,BBOX(0,40,10,50))", 7}, | ||
{"ne_110m_rivers_lake_centerlines", "S_INTERSECTS(geom,BBOX(-180,-90,0,90))", 4} | ||
}); | ||
} | ||
|
||
public @Test void testConformance() throws CQLException, IOException { | ||
DataStore ds = naturalEarthData(); | ||
int feat = featuresReturned(ds); | ||
ds.dispose(); | ||
|
||
assertEquals(this.expectedFeatures, feat); | ||
} | ||
|
||
private int featuresReturned(DataStore ds) throws CQLException, IOException { | ||
Filter filter = CQL2.toFilter(this.criteria); | ||
return ds.getFeatureSource(this.dataset).getFeatures(filter).size(); | ||
} | ||
} |
121 changes: 121 additions & 0 deletions
121
.../src/test/java/org/geotools/filter/text/cql_2/conformance/ConformanceTest8OnlineTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package org.geotools.filter.text.cql_2.conformance; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
|
||
import java.io.IOException; | ||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import org.geootols.filter.text.cql_2.CQL2; | ||
import org.geotools.api.data.DataStore; | ||
import org.geotools.api.filter.Filter; | ||
import org.geotools.filter.text.cql2.CQLException; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
import org.junit.runners.Parameterized; | ||
|
||
/** See table 7 from section A.3.5 Conformance test 8. */ | ||
@RunWith(Parameterized.class) | ||
public class ConformanceTest8OnlineTest extends ATSOnlineTest { | ||
|
||
private final String dataset; | ||
private final String criteria; | ||
private final int expectedFeatures; | ||
|
||
public ConformanceTest8OnlineTest(String dataset, String criteria, int expectedFeatures) { | ||
this.dataset = dataset; | ||
this.criteria = criteria; | ||
this.expectedFeatures = expectedFeatures; | ||
} | ||
|
||
@Parameterized.Parameters(name = "{index} {0} {1}") | ||
public static Collection<Object[]> params() { | ||
return Arrays.asList( | ||
new Object[][] { | ||
{"ne_110m_admin_0_countries", "NAME='Luxembourg'", 1}, | ||
{"ne_110m_admin_0_countries", "NAME>='Luxembourg'", 84}, | ||
{"ne_110m_admin_0_countries", "NAME>'Luxembourg'", 83}, | ||
{"ne_110m_admin_0_countries", "NAME<='Luxembourg'", 94}, | ||
{"ne_110m_admin_0_countries", "NAME<'Luxembourg'", 93}, | ||
{"ne_110m_admin_0_countries", "NAME<>'Luxembourg'", 176}, | ||
{"ne_110m_admin_0_countries", "POP_EST=37589262", 1}, | ||
{"ne_110m_admin_0_countries", "POP_EST>=37589262", 39}, | ||
{"ne_110m_admin_0_countries", "POP_EST>37589262", 38}, | ||
{"ne_110m_admin_0_countries", "POP_EST<=37589262", 139}, | ||
{"ne_110m_admin_0_countries", "POP_EST<37589262", 138}, | ||
{"ne_110m_admin_0_countries", "POP_EST<>37589262", 176}, | ||
{"ne_110m_populated_places_simple", "name IS NOT NULL", 243}, | ||
{"ne_110m_populated_places_simple", "name IS NULL", 0}, | ||
{"ne_110m_populated_places_simple", "name='København'", 1}, | ||
{"ne_110m_populated_places_simple", "name>='København'", 137}, | ||
{"ne_110m_populated_places_simple", "name>'København'", 136}, | ||
{"ne_110m_populated_places_simple", "name<='København'", 107}, | ||
{"ne_110m_populated_places_simple", "name<'København'", 106}, | ||
{"ne_110m_populated_places_simple", "name<>'København'", 242}, | ||
{"ne_110m_populated_places_simple", "pop_other IS NOT NULL", 243}, | ||
{"ne_110m_populated_places_simple", "pop_other IS NULL", 0}, | ||
{"ne_110m_populated_places_simple", "pop_other=1038288", 1}, | ||
{"ne_110m_populated_places_simple", "pop_other>=1038288", 123}, | ||
{"ne_110m_populated_places_simple", "pop_other>1038288", 122}, | ||
{"ne_110m_populated_places_simple", "pop_other<=1038288", 121}, | ||
{"ne_110m_populated_places_simple", "pop_other<1038288", 120}, | ||
{"ne_110m_populated_places_simple", "pop_other<>1038288", 242}, | ||
{"ne_110m_populated_places_simple", "\"date\" IS NOT NULL", 3}, | ||
{"ne_110m_populated_places_simple", "\"date\" IS NULL", 240}, | ||
{"ne_110m_populated_places_simple", "\"date\"=DATE('2022-04-16')", 1}, | ||
{"ne_110m_populated_places_simple", "\"date\">=DATE('2022-04-16')", 2}, | ||
{"ne_110m_populated_places_simple", "\"date\">DATE('2022-04-16')", 1}, | ||
{"ne_110m_populated_places_simple", "\"date\"<=DATE('2022-04-16')", 2}, | ||
{"ne_110m_populated_places_simple", "\"date\"<DATE('2022-04-16')", 1}, | ||
{"ne_110m_populated_places_simple", "\"date\"<>DATE('2022-04-16')", 2}, | ||
{"ne_110m_populated_places_simple", "start IS NOT NULL", 3}, | ||
{"ne_110m_populated_places_simple", "start IS NULL", 240}, | ||
{ | ||
"ne_110m_populated_places_simple", | ||
"start=TIMESTAMP('2022-04-16T10:13:19Z')", | ||
1 | ||
}, | ||
{ | ||
"ne_110m_populated_places_simple", | ||
"start<=TIMESTAMP('2022-04-16T10:13:19Z')", | ||
2 | ||
}, | ||
{ | ||
"ne_110m_populated_places_simple", | ||
"start<TIMESTAMP('2022-04-16T10:13:19Z')", | ||
1 | ||
}, | ||
{ | ||
"ne_110m_populated_places_simple", | ||
"start>=TIMESTAMP('2022-04-16T10:13:19Z')", | ||
2 | ||
}, | ||
{ | ||
"ne_110m_populated_places_simple", | ||
"start>TIMESTAMP('2022-04-16T10:13:19Z')", | ||
1 | ||
}, | ||
{ | ||
"ne_110m_populated_places_simple", | ||
"start<>TIMESTAMP('2022-04-16T10:13:19Z')", | ||
2 | ||
}, | ||
{"ne_110m_populated_places_simple", "boolean IS NOT NULL", 3}, | ||
{"ne_110m_populated_places_simple", "boolean IS NULL", 240}, | ||
{"ne_110m_populated_places_simple", "boolean=true", 2}, | ||
{"ne_110m_populated_places_simple", "boolean=false", 1} | ||
}); | ||
} | ||
|
||
public @Test void testConformance() throws CQLException, IOException { | ||
DataStore ds = naturalEarthData(); | ||
int feat = featuresReturned(ds); | ||
ds.dispose(); | ||
|
||
assertEquals(this.expectedFeatures, feat); | ||
} | ||
|
||
private int featuresReturned(DataStore ds) throws CQLException, IOException { | ||
Filter filter = CQL2.toFilter(this.criteria); | ||
return ds.getFeatureSource(this.dataset).getFeatures(filter).size(); | ||
} | ||
} |
Oops, something went wrong.