-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add macro to test all implementations (#135)
* add macro to test all implementations * few more * Apply suggestions from code review * Double interpolation to escape quotenode * mostly passing * Eval in missing GeometryBasics methods This will be upstreamed later, but it's easier to keep track here * Add a few more GB methods + comments * Add LibGEOS geometry collection constructor * Add Downloads to Project * fix reproject test * test most of the rest * fix macro names * more tests * fix macro inputs * Update barycentric.jl * put string in testset name * mls * mostly passing * Remove LibGEOS eval * new macros * refactor tests * bugfix title --------- Co-authored-by: Anshul Singhvi <anshulsinghvi@gmail.com>
- Loading branch information
1 parent
1e4311a
commit 266454d
Showing
32 changed files
with
1,025 additions
and
775 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
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
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
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
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
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 |
---|---|---|
@@ -1,22 +1,23 @@ | ||
import GeometryOps as GO, GeoInterface as GI | ||
using FlexiJoins, DataFrames | ||
using Test | ||
using FlexiJoins | ||
using DataFrames | ||
import GeometryOps as GO | ||
import GeoInterface as GI | ||
using ..TestHelpers | ||
|
||
points = GI.MultiPoint(tuple.(rand(100), rand(100))) | ||
|
||
pl = GI.Polygon([GI.LinearRing([(0, 0), (1, 0), (1, 1), (0, 0)])]) | ||
pu = GI.Polygon([GI.LinearRing([(0, 0), (0, 1), (1, 1), (0, 0)])]) | ||
poly_df = DataFrame(geometry = [pl, pu], color = [:red, :blue]) | ||
|
||
points = tuple.(rand(100), rand(100)) | ||
points_df = DataFrame(geometry = points) | ||
|
||
@testset "Basic integration" begin | ||
|
||
@test_nowarn joined_df = FlexiJoins.innerjoin((poly_df, points_df), by_pred(:geometry, GO.contains, :geometry)) | ||
@testset_implementations "Polygon DataDrame" begin | ||
points_df = DataFrame(geometry=collect(GI.getpoint($points))) | ||
poly_df = DataFrame(geometry=[$pl, $pu], color=[:red, :blue]) | ||
# Test that the join happened correctly | ||
joined_df = FlexiJoins.innerjoin((poly_df, points_df), by_pred(:geometry, GO.contains, :geometry)) | ||
@test all(GO.contains.((pl,), joined_df.geometry_1[joined_df.color .== :red])) | ||
@test all(GO.contains.((pu,), joined_df.geometry_1[joined_df.color .== :blue])) | ||
@test all(GO.contains.(($pl,), joined_df.geometry_1[joined_df.color .== :red])) | ||
@test all(GO.contains.(($pu,), joined_df.geometry_1[joined_df.color .== :blue])) | ||
# Test that within also works | ||
@test_nowarn joined_df = FlexiJoins.innerjoin((points_df, poly_df), by_pred(:geometry, GO.within, :geometry)) | ||
|
||
end | ||
|
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,119 @@ | ||
module TestHelpers | ||
|
||
using Test, GeoInterface, ArchGDAL, GeometryBasics, LibGEOS | ||
|
||
export @test_implementations, @testset_implementations | ||
|
||
const TEST_MODULES = [GeoInterface, ArchGDAL, GeometryBasics, LibGEOS] | ||
|
||
# Monkey-patch GeometryBasics to have correct methods. | ||
# TODO: push this up to GB! | ||
|
||
@eval GeometryBasics begin | ||
# MultiGeometry ncoord implementations | ||
GeoInterface.ncoord(::GeoInterface.MultiPolygonTrait, ::GeometryBasics.MultiPolygon{N}) where N = N | ||
GeoInterface.ncoord(::GeoInterface.MultiLineStringTrait, ::GeometryBasics.MultiLineString{N}) where N = N | ||
GeoInterface.ncoord(::GeoInterface.MultiPointTrait, ::GeometryBasics.MultiPoint{N}) where N = N | ||
# LinearRing and LineString confusion | ||
GeometryBasics.geointerface_geomtype(::GeoInterface.LinearRingTrait) = LineString | ||
function GeoInterface.convert(::Type{LineString}, ::GeoInterface.LinearRingTrait, geom) | ||
return GeoInterface.convert(LineString, GeoInterface.LineStringTrait(), geom) # forward to the linestring conversion method | ||
end | ||
# Line interface | ||
GeometryBasics.geointerface_geomtype(::GeoInterface.LineTrait) = Line | ||
function GeoInterface.convert(::Type{Line}, ::GeoInterface.LineTrait, geom) | ||
p1, p2 = GeoInterface.getpoint(geom) | ||
return Line(GeoInterface.convert(Point, GeoInterface.PointTrait(), p1), GeoInterface.convert(Point, GeoInterface.PointTrait(), p2)) | ||
end | ||
# GeometryCollection interface - currently just a large Union | ||
const _ALL_GB_GEOM_TYPES = Union{Point, Line, LineString, Polygon, MultiPolygon, MultiLineString, MultiPoint} | ||
GeometryBasics.geointerface_geomtype(::GeoInterface.GeometryCollectionTrait) = Vector{_ALL_GB_GEOM_TYPES} | ||
function GeoInterface.convert(::Type{Vector{_ALL_GB_GEOM_TYPES}}, ::GeoInterface.GeometryCollectionTrait, geoms) | ||
return _ALL_GB_GEOM_TYPES[GeoInterface.convert(GeometryBasics, g) for g in GeoInterface.getgeom(geoms)] | ||
end | ||
end | ||
|
||
|
||
# Macro to run a block of `code` for multiple modules, | ||
# using GeoInterface.convert for each var in `args` | ||
macro test_implementations(code::Expr) | ||
_test_implementations_inner(TEST_MODULES, code) | ||
end | ||
macro test_implementations(modules::Union{Expr,Vector}, code::Expr) | ||
_test_implementations_inner(modules, code) | ||
end | ||
|
||
function _test_implementations_inner(modules::Union{Expr,Vector}, code::Expr) | ||
vars = Dict{Symbol,Symbol}() | ||
code1 = _quasiquote!(code, vars) | ||
modules1 = modules isa Expr ? modules.args : modules | ||
tests = Expr(:block) | ||
|
||
for mod in modules1 | ||
expr = Expr(:block) | ||
for (var, genkey) in pairs(vars) | ||
push!(expr.args, :($genkey = $GeoInterface.convert($mod, $var))) | ||
end | ||
push!(expr.args, :(@test $code1)) | ||
push!(tests.args, expr) | ||
end | ||
|
||
return esc(tests) | ||
end | ||
|
||
# Macro to run a block of `code` for multiple modules, | ||
# using GeoInterface.convert for each var in `args` | ||
macro testset_implementations(code::Expr) | ||
_testset_implementations_inner("", TEST_MODULES, code) | ||
end | ||
macro testset_implementations(arg, code::Expr) | ||
if arg isa String || arg isa Expr && arg.head == :string | ||
_testset_implementations_inner(arg, TEST_MODULES, code) | ||
else | ||
_testset_implementations_inner("", arg, code) | ||
end | ||
end | ||
macro testset_implementations(title, modules::Union{Expr,Vector}, code::Expr) | ||
_testset_implementations_inner(title, modules, code) | ||
end | ||
|
||
function _testset_implementations_inner(title, modules::Union{Expr,Vector}, code::Expr) | ||
vars = Dict{Symbol,Symbol}() | ||
code1 = _quasiquote!(code, vars) | ||
modules1 = modules isa Expr ? modules.args : modules | ||
testsets = Expr(:block) | ||
|
||
for mod in modules1 | ||
expr = Expr(:block) | ||
for (var, genkey) in pairs(vars) | ||
push!(expr.args, :($genkey = $GeoInterface.convert($mod, $var))) | ||
end | ||
label = title == "" ? "$mod" : "$title: $mod" | ||
push!(expr.args, :(@testset $label $code1)) | ||
push!(testsets.args, expr) | ||
end | ||
|
||
return esc(testsets) | ||
end | ||
|
||
# Taken from BenchmarkTools.jl | ||
_quasiquote!(ex, vars) = ex | ||
function _quasiquote!(ex::Expr, vars::Dict) | ||
if ex.head === :($) | ||
v = ex.args[1] | ||
gen = if v isa Symbol | ||
haskey(vars, v) ? vars[v] : gensym(v) | ||
else | ||
gensym() | ||
end | ||
vars[v] = gen | ||
return v | ||
elseif ex.head !== :quote | ||
for i in 1:length(ex.args) | ||
ex.args[i] = _quasiquote!(ex.args[i], vars) | ||
end | ||
end | ||
return ex | ||
end | ||
|
||
end |
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
Oops, something went wrong.