From d95e9737da2d997f146fe5f2642d27ce51660e41 Mon Sep 17 00:00:00 2001 From: Sarah Hoffmann Date: Wed, 9 Apr 2025 14:57:39 +0200 Subject: [PATCH] remove usage of behave --- .github/workflows/ci-tests.yml | 6 +- Makefile | 3 +- test/Makefile | 10 - test/bdd/.behaverc | 3 - test/bdd/db/import/addressing.feature | 565 ----------------- test/bdd/db/import/country.feature | 92 --- test/bdd/db/import/interpolation.feature | 617 ------------------ test/bdd/db/import/linking.feature | 331 ---------- test/bdd/db/import/naming.feature | 105 ---- test/bdd/db/import/parenting.feature | 652 -------------------- test/bdd/db/import/placex.feature | 194 ------ test/bdd/db/import/postcodes.feature | 210 ------- test/bdd/db/import/rank_computation.feature | 300 --------- test/bdd/db/import/search_name.feature | 428 ------------- test/bdd/db/query/housenumbers.feature | 321 ---------- test/bdd/db/query/interpolation.feature | 58 -- test/bdd/db/query/japanese.feature | 29 - test/bdd/db/query/linking.feature | 64 -- test/bdd/db/query/normalization.feature | 226 ------- test/bdd/db/query/postcodes.feature | 110 ---- test/bdd/db/query/reverse.feature | 22 - test/bdd/db/query/search_simple.feature | 108 ---- test/bdd/db/update/country.feature | 109 ---- test/bdd/db/update/interpolation.feature | 419 ------------- test/bdd/db/update/linked_places.feature | 341 ---------- test/bdd/db/update/naming.feature | 21 - test/bdd/db/update/parenting.feature | 164 ----- test/bdd/db/update/postcode.feature | 119 ---- test/bdd/db/update/simple.feature | 116 ---- test/bdd/environment.py | 64 -- test/bdd/steps/check_functions.py | 99 --- test/bdd/steps/geometry_alias.py | 262 -------- test/bdd/steps/geometry_factory.py | 88 --- test/bdd/steps/http_responses.py | 253 -------- test/bdd/steps/nominatim_environment.py | 315 ---------- test/bdd/steps/place_inserter.py | 120 ---- test/bdd/steps/steps_api_queries.py | 307 --------- test/bdd/steps/steps_db_ops.py | 464 -------------- test/bdd/steps/steps_osm_data.py | 144 ----- test/bdd/steps/table_compare.py | 230 ------- 40 files changed, 3 insertions(+), 8086 deletions(-) delete mode 100644 test/Makefile delete mode 100644 test/bdd/.behaverc delete mode 100644 test/bdd/db/import/addressing.feature delete mode 100644 test/bdd/db/import/country.feature delete mode 100644 test/bdd/db/import/interpolation.feature delete mode 100644 test/bdd/db/import/linking.feature delete mode 100644 test/bdd/db/import/naming.feature delete mode 100644 test/bdd/db/import/parenting.feature delete mode 100644 test/bdd/db/import/placex.feature delete mode 100644 test/bdd/db/import/postcodes.feature delete mode 100644 test/bdd/db/import/rank_computation.feature delete mode 100644 test/bdd/db/import/search_name.feature delete mode 100644 test/bdd/db/query/housenumbers.feature delete mode 100644 test/bdd/db/query/interpolation.feature delete mode 100644 test/bdd/db/query/japanese.feature delete mode 100644 test/bdd/db/query/linking.feature delete mode 100644 test/bdd/db/query/normalization.feature delete mode 100644 test/bdd/db/query/postcodes.feature delete mode 100644 test/bdd/db/query/reverse.feature delete mode 100644 test/bdd/db/query/search_simple.feature delete mode 100644 test/bdd/db/update/country.feature delete mode 100644 test/bdd/db/update/interpolation.feature delete mode 100644 test/bdd/db/update/linked_places.feature delete mode 100644 test/bdd/db/update/naming.feature delete mode 100644 test/bdd/db/update/parenting.feature delete mode 100644 test/bdd/db/update/postcode.feature delete mode 100644 test/bdd/db/update/simple.feature delete mode 100644 test/bdd/environment.py delete mode 100644 test/bdd/steps/check_functions.py delete mode 100644 test/bdd/steps/geometry_alias.py delete mode 100644 test/bdd/steps/geometry_factory.py delete mode 100644 test/bdd/steps/http_responses.py delete mode 100644 test/bdd/steps/nominatim_environment.py delete mode 100644 test/bdd/steps/place_inserter.py delete mode 100644 test/bdd/steps/steps_api_queries.py delete mode 100644 test/bdd/steps/steps_db_ops.py delete mode 100644 test/bdd/steps/steps_osm_data.py delete mode 100644 test/bdd/steps/table_compare.py diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 520fcff8..4b7a7483 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -94,7 +94,7 @@ jobs: if: matrix.dependencies == 'pip' - name: Install test prerequisites - run: ./venv/bin/pip install behave==1.2.6 pytest-bdd + run: ./venv/bin/pip install pytest-bdd - name: Install latest flake8 run: ./venv/bin/pip install -U flake8 @@ -118,9 +118,7 @@ jobs: - name: BDD tests run: | - ../venv/bin/python -m pytest test/bdd - cd test/bdd - ../../../venv/bin/python -m behave -DREMOVE_TEMPLATE=1 --format=progress3 db osm2pgsql + ../venv/bin/python -m pytest test/bdd --nominatim-purge working-directory: Nominatim install: diff --git a/Makefile b/Makefile index 864e9385..d6423add 100644 --- a/Makefile +++ b/Makefile @@ -27,8 +27,7 @@ lint: flake8 src test/python test/bdd bdd: - pytest test/bdd - cd test/bdd; behave -DREMOVE_TEMPLATE=1 db osm2pgsql + pytest test/bdd --nominatim-purge # Documentation diff --git a/test/Makefile b/test/Makefile deleted file mode 100644 index 9768ebd7..00000000 --- a/test/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -all: bdd python - -bdd: - cd bdd && behave -DREMOVE_TEMPLATE=1 - -python: - pytest python - - -.PHONY: bdd python diff --git a/test/bdd/.behaverc b/test/bdd/.behaverc deleted file mode 100644 index 1b426ec9..00000000 --- a/test/bdd/.behaverc +++ /dev/null @@ -1,3 +0,0 @@ -[behave] -show_skipped=False -default_tags=~@Fail diff --git a/test/bdd/db/import/addressing.feature b/test/bdd/db/import/addressing.feature deleted file mode 100644 index e7c91207..00000000 --- a/test/bdd/db/import/addressing.feature +++ /dev/null @@ -1,565 +0,0 @@ -@DB -Feature: Address computation - Tests for filling of place_addressline - - Scenario: place nodes are added to the address when they are close enough - Given the 0.002 grid - | 2 | | | | | | 1 | | 3 | - And the places - | osm | class | type | name | geometry | - | N1 | place | square | Square | 1 | - | N2 | place | hamlet | West Farm | 2 | - | N3 | place | hamlet | East Farm | 3 | - When importing - Then place_addressline contains - | object | address | fromarea | - | N1 | N3 | False | - Then place_addressline doesn't contain - | object | address | - | N1 | N2 | - When sending search query "Square" - Then results contain - | osm | display_name | - | N1 | Square, East Farm | - - Scenario: given two place nodes, the closer one wins for the address - Given the grid - | 2 | | | 1 | | 3 | - And the named places - | osm | class | type | geometry | - | N1 | place | square | 1 | - | N2 | place | hamlet | 2 | - | N3 | place | hamlet | 3 | - When importing - Then place_addressline contains - | object | address | fromarea | isaddress | - | N1 | N3 | False | True | - | N1 | N2 | False | False | - - Scenario: boundaries around the place are added to the address - Given the grid - | 1 | | 4 | | 7 | 10 | - | 2 | | 5 | | 8 | 11 | - | | | | | | | - | | | | | | | - | | | 6 | | 9 | | - | | 99 | | | | | - | 3 | | | | | 12 | - And the named places - | osm | class | type | admin | geometry | - | R1 | boundary | administrative | 3 | (1,2,3,12,11,10,7,8,9,6,5,4,1) | - | R2 | boundary | administrative | 4 | (2,3,12,11,8,9,6,5,2) | - | N1 | place | square | 15 | 99 | - When importing - Then place_addressline contains - | object | address | isaddress | - | N1 | R1 | True | - | N1 | R2 | True | - - Scenario: with boundaries of same rank the one with the closer centroid is preferred - Given the grid - | 1 | | | 3 | | 5 | - | | 9 | | | | | - | 2 | | | 4 | | 6 | - And the named places - | osm | class | type | admin | geometry | - | R1 | boundary | administrative | 8 | (1,2,4,3,1) | - | R2 | boundary | administrative | 8 | (1,2,6,5,1) | - | N1 | place | square | 15 | 9 | - When importing - Then place_addressline contains - | object | address | isaddress | - | N1 | R1 | True | - | N1 | R2 | False | - - Scenario: boundary areas are preferred over place nodes in the address - Given the grid - | 1 | | | | 10 | | 3 | - | | 5 | | | | | | - | | 6 | | | | | | - | 2 | | | | 11 | | 4 | - And the named places - | osm | class | type | admin | geometry | - | N1 | place | square | 15 | 5 | - | N2 | place | city | 15 | 6 | - | R1 | place | city | 8 | (1,2,4,3,1) | - | R2 | boundary | administrative | 9 | (1,10,11,2,1) | - When importing - Then place_addressline contains - | object | address | isaddress | cached_rank_address | - | N1 | R1 | True | 16 | - | N1 | R2 | True | 18 | - | N1 | N2 | False | 18 | - - Scenario: place nodes outside a smaller ranked area are ignored - Given the grid - | 1 | | 2 | | - | | 7 | | 9 | - | 4 | | 3 | | - And the named places - | osm | class | type | admin | geometry | - | N1 | place | square | 15 | 7 | - | N2 | place | city | 15 | 9 | - | R1 | place | city | 8 | (1,2,3,4,1) | - When importing - Then place_addressline contains - | object | address | isaddress | cached_rank_address | - | N1 | R1 | True | 16 | - And place_addressline doesn't contain - | object | address | - | N1 | N2 | - - - Scenario: place nodes close enough to smaller ranked place nodes are included - Given the 0.002 grid - | 2 | | 3 | 1 | - And the named places - | osm | class | type | geometry | - | N1 | place | square | 1 | - | N2 | place | hamlet | 2 | - | N3 | place | quarter | 3 | - When importing - Then place_addressline contains - | object | address | fromarea | isaddress | - | N1 | N2 | False | True | - | N1 | N3 | False | True | - - - Scenario: place nodes too far away from a smaller ranked place nodes are marked non-address - Given the 0.002 grid - | 2 | | | 1 | | 3 | - And the named places - | osm | class | type | geometry | - | N1 | place | square | 1 | - | N2 | place | hamlet | 2 | - | N3 | place | quarter | 3 | - When importing - Then place_addressline contains - | object | address | fromarea | isaddress | - | N1 | N2 | False | True | - | N1 | N3 | False | False | - - - # github #121 - Scenario: Roads crossing boundaries should contain both states - Given the grid - | 1 | | | 2 | | 3 | - | | 7 | | | 8 | | - | 4 | | | 5 | | 6 | - And the named places - | osm | class | type | geometry | - | W1 | highway | road | 7, 8 | - And the named places - | osm | class | type | admin | geometry | - | W10 | boundary | administrative | 5 | (1, 2, 5, 4, 1) | - | W11 | boundary | administrative | 5 | (2, 3, 6, 5, 2) | - When importing - Then place_addressline contains - | object | address | cached_rank_address | - | W1 | W10 | 10 | - | W1 | W11 | 10 | - - - Scenario: Roads following a boundary should contain both states - Given the grid - | 1 | | | 2 | | 3 | - | | | 8 | 7 | | | - | 4 | | | 5 | | 6 | - And the named places - | osm | class | type | geometry | - | W1 | highway | road | 2, 7, 8 | - And the named places - | osm | class | type | admin | geometry | - | W10 | boundary | administrative | 5 | (1, 2, 5, 4, 1) | - | W11 | boundary | administrative | 5 | (2, 3, 6, 5, 2) | - When importing - Then place_addressline contains - | object | address | cached_rank_address | - | W1 | W10 | 10 | - | W1 | W11 | 10 | - - Scenario: Roads should not contain boundaries they touch in a end point - Given the grid - | 1 | | | 2 | | 3 | - | | 7 | | 8 | | | - | 4 | | | 5 | | 6 | - And the named places - | osm | class | type | geometry | - | W1 | highway | road | 7, 8 | - And the named places - | osm | class | type | admin | geometry | - | W10 | boundary | administrative | 5 | (1, 2, 8, 5, 4, 1) | - | W11 | boundary | administrative | 5 | (2, 3, 6, 5, 8, 2) | - When importing - Then place_addressline contains - | object | address | cached_rank_address | - | W1 | W10 | 10 | - Then place_addressline doesn't contain - | object | address | - | W1 | W11 | - - Scenario: Roads should not contain boundaries they touch in a middle point - Given the grid - | 1 | | | 2 | | 3 | - | | 7 | | 8 | | | - | 4 | | 9 | 5 | | 6 | - And the named places - | osm | class | type | geometry | - | W1 | highway | road | 7, 8, 9 | - And the named places - | osm | class | type | admin | geometry | - | W10 | boundary | administrative | 5 | (1, 2, 8, 5, 4, 1) | - | W11 | boundary | administrative | 5 | (2, 3, 6, 5, 8, 2) | - When importing - Then place_addressline contains - | object | address | cached_rank_address | - | W1 | W10 | 10 | - Then place_addressline doesn't contain - | object | address | - | W1 | W11 | - - Scenario: Locality points should contain all boundaries they touch - Given the 0.001 grid - | 1 | | | 2 | | 3 | - | | | | 8 | | | - | 4 | | | 5 | | 6 | - And the named places - | osm | class | type | geometry | - | N1 | place | locality | 8 | - And the named places - | osm | class | type | admin | geometry | - | W10 | boundary | administrative | 5 | (1, 2, 8, 5, 4, 1) | - | W11 | boundary | administrative | 5 | (2, 3, 6, 5, 8, 2) | - When importing - Then place_addressline contains - | object | address | cached_rank_address | - | N1 | W10 | 10 | - | N1 | W11 | 10 | - - Scenario: Areas should not contain boundaries they touch - Given the grid - | 1 | | | 2 | | 3 | - | | | | | | | - | 4 | | | 5 | | 6 | - And the named places - | osm | class | type | geometry | - | W1 | landuse | industrial | (1, 2, 5, 4, 1) | - And the named places - | osm | class | type | admin | geometry | - | W10 | boundary | administrative | 5 | (2, 3, 6, 5, 2) | - When importing - Then place_addressline doesn't contain - | object | address | - | W1 | W10 | - - Scenario: buildings with only addr:postcodes do not appear in the address of a way - Given the grid with origin DE - | 1 | | | | | 8 | | 6 | | 2 | - | |10 |11 | | | | | | | | - | |13 |12 | | | | | | | | - | 20| | | 21| | | | | | | - | | | | | | | | | | | - | | | | | | 9 | | | | | - | 4 | | | | | | | 7 | | 3 | - And the named places - | osm | class | type | admin | addr+postcode | geometry | - | R1 | boundary | administrative | 6 | 10000 | (1,2,3,4,1)| - | R34 | boundary | administrative | 8 | 11200 | (1,6,7,4,1)| - | R4 | boundary | administrative | 10 | 11230 | (1,8,9,4,1)| - And the named places - | osm | class | type | geometry | - | W93 | highway | residential | 20,21 | - And the places - | osm | class | type | addr+postcode | geometry | - | W22 | place | postcode | 11234 | (10,11,12,13,10) | - When importing - Then place_addressline doesn't contain - | object | address | - | W93 | W22 | - - Scenario: postcode boundaries do appear in the address of a way - Given the grid with origin DE - | 1 | | | | | 8 | | 6 | | 2 | - | |10 |11 | | | | | | | | - | |13 |12 | | | | | | | | - | 20| | | 21| | | | | | | - | | | | | | | | | | | - | | | | | | 9 | | | | | - | 4 | | | | | | | 7 | | 3 | - And the named places - | osm | class | type | admin | addr+postcode | geometry | - | R1 | boundary | administrative | 6 | 10000 | (1,2,3,4,1) | - | R34 | boundary | administrative | 8 | 11000 | (1,6,7,4,1) | - And the places - | osm | class | type | addr+postcode | geometry | - | R4 | boundary | postal_code | 11200 | (1,8,9,4,1) | - And the named places - | osm | class | type | geometry | - | W93 | highway | residential | 20,21 | - And the places - | osm | class | type | addr+postcode | geometry | - | W22 | place | postcode | 11234 | (10,11,12,13,10) | - When importing - Then place_addressline contains - | object | address | - | W93 | R4 | - - Scenario: squares do not appear in the address of a street - Given the grid - | | 1 | | 2 | | - | 8 | | | | 9 | - | | 4 | | 3 | | - And the named places - | osm | class | type | geometry | - | W1 | highway | residential | 8, 9 | - | W2 | place | square | (1, 2, 3 ,4, 1) | - When importing - Then place_addressline doesn't contain - | object | address | - | W1 | W2 | - - Scenario: addr:* tags are honored even when a street is far away from the place - Given the grid - | 1 | | 2 | | | 5 | - | | | | 8 | 9 | | - | 4 | | 3 | | | 6 | - And the places - | osm | class | type | admin | name | geometry | - | R1 | boundary | administrative | 8 | Left | (1,2,3,4,1) | - | R2 | boundary | administrative | 8 | Right | (2,3,6,5,2) | - And the places - | osm | class | type | addr+city | geometry | - | W1 | highway | primary | Left | 8,9 | - | W2 | highway | primary | Right | 8,9 | - When importing - Then place_addressline contains - | object | address | isaddress | - | W1 | R1 | True | - | W1 | R2 | False | - | W2 | R2 | True | - And place_addressline doesn't contain - | object | address | - | W2 | R1 | - - - Scenario: addr:* tags are honored even when a POI is far away from the place - Given the grid - | 1 | | 2 | | | 5 | - | | | | 8 | 9 | | - | 4 | | 3 | | | 6 | - And the places - | osm | class | type | admin | name | geometry | - | R1 | boundary | administrative | 8 | Left | (1,2,3,4,1) | - | R2 | boundary | administrative | 8 | Right | (2,3,6,5,2) | - And the places - | osm | class | type | name | addr+city | geometry | - | W1 | highway | primary | Wonderway | Right | 8,9 | - | N1 | amenity | cafe | Bolder | Left | 9 | - When importing - Then place_addressline contains - | object | address | isaddress | - | W1 | R2 | True | - | N1 | R1 | True | - And place_addressline doesn't contain - | object | address | - | W1 | R1 | - When sending search query "Bolder" - Then results contain - | osm | display_name | - | N1 | Bolder, Wonderway, Left | - - Scenario: addr:* tags do not produce addresslines when the parent has the address part - Given the grid - | 1 | | | 5 | - | | 8 | 9 | | - | 4 | | | 6 | - And the places - | osm | class | type | admin | name | geometry | - | R1 | boundary | administrative | 8 | Outer | (1,5,6,4,1) | - And the places - | osm | class | type | name | addr+city | geometry | - | W1 | highway | primary | Wonderway | Outer | 8,9 | - | N1 | amenity | cafe | Bolder | Outer | 9 | - When importing - Then place_addressline contains - | object | address | isaddress | - | W1 | R1 | True | - And place_addressline doesn't contain - | object | address | - | N1 | R1 | - When sending search query "Bolder" - Then results contain - | osm | display_name | - | N1 | Bolder, Wonderway, Outer | - - Scenario: addr:* tags on outside do not produce addresslines when the parent has the address part - Given the grid - | 1 | | 2 | | | 5 | - | | | | 8 | 9 | | - | 4 | | 3 | | | 6 | - And the places - | osm | class | type | admin | name | geometry | - | R1 | boundary | administrative | 8 | Left | (1,2,3,4,1) | - | R2 | boundary | administrative | 8 | Right | (2,3,6,5,2) | - And the places - | osm | class | type | name | addr+city | geometry | - | W1 | highway | primary | Wonderway | Left | 8,9 | - | N1 | amenity | cafe | Bolder | Left | 9 | - When importing - Then place_addressline contains - | object | address | isaddress | - | W1 | R1 | True | - | W1 | R2 | False | - And place_addressline doesn't contain - | object | address | - | N1 | R1 | - When sending search query "Bolder" - Then results contain - | osm | display_name | - | N1 | Bolder, Wonderway, Left | - - Scenario: POIs can correct address parts on the fly - Given the grid - | 1 | | | | 2 | | 5 | - | | | | 9 | | 8 | | - | 4 | | | | 3 | | 6 | - And the places - | osm | class | type | admin | name | geometry | - | R1 | boundary | administrative | 8 | Left | (1,2,3,4,1) | - | R2 | boundary | administrative | 8 | Right | (2,3,6,5,2) | - And the places - | osm | class | type | name | geometry | - | W1 | highway | primary | Wonderway | 2,3 | - | N1 | amenity | cafe | Bolder | 9 | - | N2 | amenity | cafe | Leftside | 8 | - When importing - Then place_addressline contains - | object | address | isaddress | - | W1 | R1 | False | - | W1 | R2 | True | - And place_addressline doesn't contain - | object | address | - | N1 | R1 | - | N2 | R2 | - When sending search query "Bolder" - Then results contain - | osm | display_name | - | N1 | Bolder, Wonderway, Left | - When sending search query "Leftside" - Then results contain - | osm | display_name | - | N2 | Leftside, Wonderway, Right | - - - Scenario: POIs can correct address parts on the fly (with partial unmatching address) - Given the grid - | 1 | | | | 2 | | 5 | - | | | | 9 | | 8 | | - | | 10| 11| | | 12| | - | 4 | | | | 3 | | 6 | - And the places - | osm | class | type | admin | name | geometry | - | R1 | boundary | administrative | 8 | Left | (1,2,3,4,1) | - | R2 | boundary | administrative | 8 | Right | (2,3,6,5,2) | - And the places - | osm | class | type | name | geometry | - | W1 | highway | primary | Wonderway | 10,11,12 | - And the places - | osm | class | type | name | addr+suburb | geometry | - | N1 | amenity | cafe | Bolder | Boring | 9 | - | N2 | amenity | cafe | Leftside | Boring | 8 | - When importing - Then place_addressline contains - | object | address | isaddress | - | W1 | R1 | True | - | W1 | R2 | False | - And place_addressline doesn't contain - | object | address | - | N1 | R1 | - | N2 | R2 | - When sending search query "Bolder" - Then results contain - | osm | display_name | - | N1 | Bolder, Wonderway, Left | - When sending search query "Leftside" - Then results contain - | osm | display_name | - | N2 | Leftside, Wonderway, Right | - - - - Scenario: POIs can correct address parts on the fly (with partial matching address) - Given the grid - | 1 | | | | 2 | | 5 | - | | | | 9 | | 8 | | - | | 10| 11| | | 12| | - | 4 | | | | 3 | | 6 | - And the places - | osm | class | type | admin | name | geometry | - | R1 | boundary | administrative | 8 | Left | (1,2,3,4,1) | - | R2 | boundary | administrative | 8 | Right | (2,3,6,5,2) | - And the places - | osm | class | type | name | geometry | - | W1 | highway | primary | Wonderway | 10,11,12 | - And the places - | osm | class | type | name | addr+state | geometry | - | N1 | amenity | cafe | Bolder | Left | 9 | - | N2 | amenity | cafe | Leftside | Left | 8 | - When importing - Then place_addressline contains - | object | address | isaddress | - | W1 | R1 | True | - | W1 | R2 | False | - And place_addressline doesn't contain - | object | address | - | N1 | R1 | - | N2 | R2 | - When sending search query "Bolder" - Then results contain - | osm | display_name | - | N1 | Bolder, Wonderway, Left | - When sending search query "Leftside" - Then results contain - | osm | display_name | - | N2 | Leftside, Wonderway, Left | - - - Scenario: addr:* tags always match the closer area - Given the grid - | 1 | | | | 2 | | 5 | - | | | | | | | | - | | 10| 11| | | | | - | 4 | | | | 3 | | 6 | - And the places - | osm | class | type | admin | name | geometry | - | R1 | boundary | administrative | 8 | Left | (1,2,3,4,1) | - | R2 | boundary | administrative | 8 | Left | (2,3,6,5,2) | - And the places - | osm | class | type | name | addr+city | geometry | - | W1 | highway | primary | Wonderway | Left | 10,11 | - When importing - Then place_addressline doesn't contain - | object | address | - | W1 | R2 | - - Scenario: Full name is prefered for unlisted addr:place tags - Given the grid - | | 1 | 2 | | - | 8 | | | 9 | - And the places - | osm | class | type | name | geometry | - | W10 | place | city | Away | (8,1,2,9,8) | - And the places - | osm | class | type | name | addr+city | geometry | - | W1 | highway | residential | Royal Terrace | Gardens | 8,9 | - And the places - | osm | class | type | housenr | addr+place | geometry | extra+foo | - | N1 | place | house | 1 | Royal Terrace Gardens | 1 | bar | - And the places - | osm | class | type | housenr | addr+street | geometry | - | N2 | place | house | 2 | Royal Terrace | 2 | - When importing - When sending search query "1, Royal Terrace Gardens" - Then results contain - | ID | osm | - | 0 | N1 | diff --git a/test/bdd/db/import/country.feature b/test/bdd/db/import/country.feature deleted file mode 100644 index bfa46969..00000000 --- a/test/bdd/db/import/country.feature +++ /dev/null @@ -1,92 +0,0 @@ -@DB -Feature: Country handling - Tests for import and use of country information - - Scenario: Country names from OSM country relations are added - Given the places - | osm | class | type | admin | name+name:xy | country | geometry | - | R1 | boundary | administrative | 2 | Loudou | de | (9 52, 9 53, 10 52, 9 52) | - Given the places - | osm | class | type | name | geometry | - | N1 | place | town | Wenig | country:de | - When importing - When sending search query "Wenig, Loudou" - Then results contain - | osm | display_name | - | N1 | Wenig, Deutschland | - When sending search query "Wenig" - | accept-language | - | xy,en | - Then results contain - | osm | display_name | - | N1 | Wenig, Loudou | - - Scenario: OSM country relations outside expected boundaries are ignored for naming - Given the grid - | 1 | | 2 | - | 4 | | 3 | - Given the places - | osm | class | type | admin | name+name:xy | country | geometry | - | R1 | boundary | administrative | 2 | Loudou | de | (1,2,3,4,1) | - Given the places - | osm | class | type | name | geometry | - | N1 | place | town | Wenig | country:de | - When importing - When sending search query "Wenig" - | accept-language | - | xy,en | - Then results contain - | osm | display_name | - | N1 | Wenig, Germany | - - Scenario: Pre-defined country names are used - Given the grid with origin CH - | 1 | - Given the places - | osm | class | type | name | geometry | - | N1 | place | town | Ingb | 1 | - When importing - And sending search query "Ingb" - | accept-language | - | en,de | - Then results contain - | osm | display_name | - | N1 | Ingb, Switzerland | - - Scenario: For overlapping countries, pre-defined countries are tie-breakers - Given the grid with origin US - | 1 | | 2 | | 5 | - | | 9 | | 8 | | - | 4 | | 3 | | 6 | - Given the named places - | osm | class | type | admin | country | geometry | - | R1 | boundary | administrative | 2 | de | (1,5,6,4,1) | - | R2 | boundary | administrative | 2 | us | (1,2,3,4,1) | - And the named places - | osm | class | type | geometry | - | N1 | place | town | 9 | - | N2 | place | town | 8 | - When importing - Then placex contains - | object | country_code | - | N1 | us | - | N2 | de | - - Scenario: For overlapping countries outside pre-define countries prefer smaller partition - Given the grid with origin US - | 1 | | 2 | | 5 | - | | 9 | | 8 | | - | 4 | | 3 | | 6 | - Given the named places - | osm | class | type | admin | country | geometry | - | R1 | boundary | administrative | 2 | ch | (1,5,6,4,1) | - | R2 | boundary | administrative | 2 | de | (1,2,3,4,1) | - And the named places - | osm | class | type | geometry | - | N1 | place | town | 9 | - | N2 | place | town | 8 | - When importing - Then placex contains - | object | country_code | - | N1 | de | - | N2 | ch | diff --git a/test/bdd/db/import/interpolation.feature b/test/bdd/db/import/interpolation.feature deleted file mode 100644 index 6b784b78..00000000 --- a/test/bdd/db/import/interpolation.feature +++ /dev/null @@ -1,617 +0,0 @@ -@DB -Feature: Import of address interpolations - Tests that interpolated addresses are added correctly - - Scenario: Simple even interpolation line with two points and no street nearby - Given the grid with origin 1,1 - | 1 | | 9 | | 2 | - Given the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 6 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 1,2 | - And the ways - | id | nodes | - | 1 | 1,2 | - When importing - Then W1 expands to no interpolation - - Scenario: Simple even interpolation line with two points - Given the grid with origin 1,1 - | 1 | | 9 | | 2 | - | 4 | | | | 5 | - Given the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 6 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 1,2 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 4,5 | - And the ways - | id | nodes | - | 1 | 1,2 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 4 | 4 | 9 | - - Scenario: Backwards even two point interpolation line - Given the grid with origin 1,1 - | 1 | 8 | 9 | 2 | - | 4 | | | 5 | - Given the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 8 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 2,1 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 4,5 | - And the ways - | id | nodes | - | 1 | 2,1 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 4 | 6 | 9,8 | - - Scenario: Simple odd two point interpolation - Given the grid with origin 1,1 - | 1 | 8 | | | 9 | 2 | - | 4 | | | | 5 | | - Given the places - | osm | class | type | housenr | - | N1 | place | house | 1 | - | N2 | place | house | 11 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | odd | 1,2 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 4,5 | - And the ways - | id | nodes | - | 1 | 1,2 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 3 | 9 | 8,9 | - - Scenario: Simple all two point interpolation - Given the grid with origin 1,1 - | 1 | 8 | 9 | 2 | - | 4 | | | 5 | - Given the places - | osm | class | type | housenr | - | N1 | place | house | 1 | - | N2 | place | house | 4 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | all | 1,2 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 4,5 | - And the ways - | id | nodes | - | 1 | 1,2 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 2 | 3 | 8,9 | - - Scenario: Even two point interpolation line with intermediate empty node - Given the grid - | 1 | 8 | | 3 | 9 | 2 | - | 4 | | | | 5 | | - Given the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 12 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 1,3,2 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 4,5 | - And the ways - | id | nodes | - | 1 | 1,3,2 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 4 | 10 | 8,3,9 | - - Scenario: Even two point interpolation line with intermediate duplicated empty node - Given the grid - | 4 | | | | 5 | - | 1 | 8 | 3 | 9 | 2 | - Given the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 10 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 1,3,2 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 4,5 | - And the ways - | id | nodes | - | 1 | 1,3,3,2 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 4 | 8 | 8,3,9 | - - Scenario: Simple even three point interpolation line - Given the grid - | 4 | | | | | | 5 | - | 1 | 8 | | 9 | 3 | 7 | 2 | - Given the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 14 | - | N3 | place | house | 10 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 1,3,2 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 4,5 | - And the ways - | id | nodes | - | 1 | 1,3,2 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 4 | 8 | 8,9 | - | 12 | 12 | 7 | - - Scenario: Simple even four point interpolation line - Given the grid - | 1 | 10 | | 11 | 3 | - | | | | | 12| - | | | 4 | 13 | 2 | - Given the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 14 | - | N3 | place | house | 10 | - | N4 | place | house | 18 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 1,3,2,4 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 1,3,2,4 | - And the ways - | id | nodes | - | 1 | 1,3,2,4 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 4 | 8 | 10,11 | - | 12 | 12 | 12 | - | 16 | 16 | 13 | - - Scenario: Reverse simple even three point interpolation line - Given the grid - | 1 | 8 | | 9 | 3 | 7 | 2 | - | 4 | | | | | | 5 | - Given the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 14 | - | N3 | place | house | 10 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 2,3,1 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 4,5 | - And the ways - | id | nodes | - | 1 | 2,3,1 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 4 | 8 | 8,9 | - | 12 | 12 | 7 | - - Scenario: Even three point interpolation line with odd center point - Given the grid - | 1 | | 10 | | | 11 | 3 | 2 | - | 4 | | | | | | | 5 | - Given the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 8 | - | N3 | place | house | 7 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 1,3,2 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 4,5 | - And the ways - | id | nodes | - | 1 | 1,3,2 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 4 | 6 | 10,11 | - - Scenario: Interpolation line with self-intersecting way - Given the grid - | 1 | 9 | 2 | - | | | 8 | - | | | 3 | - Given the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 6 | - | N3 | place | house | 10 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 1,2,3,2 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 1,2,3 | - And the ways - | id | nodes | - | 1 | 1,2,3,2 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 4 | 4 | 9 | - | 8 | 8 | 8 | - | 8 | 8 | 8 | - - Scenario: Interpolation line with self-intersecting way II - Given the grid - | 1 | 9 | 2 | - | | | 3 | - Given the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 6 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 1,2,3,2 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 1,2,3 | - And the ways - | id | nodes | - | 1 | 1,2,3,2 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 4 | 4 | 9 | - - Scenario: addr:street on interpolation way - Given the grid - | | 1 | | 2 | | - | 10 | | | | 11 | - | 20 | | | | 21 | - And the places - | osm | class | type | housenr | geometry | - | N1 | place | house | 2 | 1 | - | N2 | place | house | 6 | 2 | - | N3 | place | house | 12 | 1 | - | N4 | place | house | 16 | 2 | - And the places - | osm | class | type | addr+interpolation | street | geometry | - | W10 | place | houses | even | | 1,2 | - | W11 | place | houses | even | Cloud Street | 1,2 | - And the places - | osm | class | type | name | geometry | - | W2 | highway | tertiary | Sun Way | 10,11 | - | W3 | highway | tertiary | Cloud Street | 20,21 | - And the ways - | id | nodes | - | 10 | 1,2 | - | 11 | 3,4 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W2 | - | N2 | W2 | - | N3 | W3 | - | N4 | W3 | - Then W10 expands to interpolation - | parent_place_id | start | end | - | W2 | 4 | 4 | - Then W11 expands to interpolation - | parent_place_id | start | end | - | W3 | 14 | 14 | - When sending search query "16 Cloud Street" - Then results contain - | ID | osm | - | 0 | N4 | - When sending search query "14 Cloud Street" - Then results contain - | ID | osm | - | 0 | W11 | - - Scenario: addr:street on housenumber way - Given the grid - | | 1 | | 2 | | - | 10 | | | | 11 | - | 20 | | | | 21 | - And the places - | osm | class | type | housenr | street | geometry | - | N1 | place | house | 2 | | 1 | - | N2 | place | house | 6 | | 2 | - | N3 | place | house | 12 | Cloud Street | 1 | - | N4 | place | house | 16 | Cloud Street | 2 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W10 | place | houses | even | 1,2 | - | W11 | place | houses | even | 1,2 | - And the places - | osm | class | type | name | geometry | - | W2 | highway | tertiary | Sun Way | 10,11 | - | W3 | highway | tertiary | Cloud Street | 20,21 | - And the ways - | id | nodes | - | 10 | 1,2 | - | 11 | 3,4 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W2 | - | N2 | W2 | - | N3 | W3 | - | N4 | W3 | - Then W10 expands to interpolation - | parent_place_id | start | end | - | W2 | 4 | 4 | - Then W11 expands to interpolation - | parent_place_id | start | end | - | W3 | 14 | 14 | - When sending search query "16 Cloud Street" - Then results contain - | ID | osm | - | 0 | N4 | - When sending search query "14 Cloud Street" - Then results contain - | ID | osm | - | 0 | W11 | - - Scenario: Geometry of points and way don't match (github #253) - Given the places - | osm | class | type | housenr | geometry | - | N1 | place | house | 10 | 144.9632341 -37.76163 | - | N2 | place | house | 6 | 144.9630541 -37.7628174 | - | N3 | shop | supermarket | 2 | 144.9629794 -37.7630755 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 144.9632341 -37.76163,144.9630541 -37.7628172,144.9629794 -37.7630755 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 144.9632341 -37.76163,144.9629794 -37.7630755 | - And the ways - | id | nodes | - | 1 | 1,2,3 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 4 | 4 | 144.963016 -37.762946 | - | 8 | 8 | 144.96314407 -37.762223692 | - - Scenario: Place with missing address information - Given the grid - | 1 | | 2 | | | 3 | - | 4 | | | | | 5 | - And the places - | osm | class | type | housenr | - | N1 | place | house | 23 | - | N2 | amenity | school | | - | N3 | place | house | 29 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | odd | 1,2,3 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 4,5 | - And the ways - | id | nodes | - | 1 | 1,2,3 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 25 | 27 | 0.000016 0,0.00002 0,0.000033 0 | - - Scenario: Ways without node entries are ignored - Given the places - | osm | class | type | housenr | geometry | - | W1 | place | houses | even | 1 1, 1 1.001 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 1 1, 1 1.001 | - When importing - Then W1 expands to no interpolation - - Scenario: Ways with nodes without housenumbers are ignored - Given the grid - | 1 | | 2 | - | 4 | | 5 | - Given the places - | osm | class | type | - | N1 | place | house | - | N2 | place | house | - Given the places - | osm | class | type | housenr | geometry | - | W1 | place | houses | even | 1,2 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 4,5 | - When importing - Then W1 expands to no interpolation - - Scenario: Two point interpolation starting at 0 - Given the grid with origin 1,1 - | 1 | 10 | | | 11 | 2 | - | 4 | | | | | 5 | - Given the places - | osm | class | type | housenr | - | N1 | place | house | 0 | - | N2 | place | house | 10 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 1,2 | - And the places - | osm | class | type | name | geometry | - | W10 | highway | residential | London Road |4,5 | - And the ways - | id | nodes | - | 1 | 1,2 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 2 | 8 | 10,11 | - When sending v1/reverse at 1,1 - Then results contain - | ID | osm | type | display_name | - | 0 | N1 | house | 0, London Road | - - Scenario: Parenting of interpolation with additional tags - Given the grid - | 1 | | | | | | - | | | | | | | - | | 8 | | | 9 | | - | | | | | | | - | 2 | | | | | 3 | - Given the places - | osm | class | type | housenr | addr+street | - | N8 | place | house | 10 | Horiz St | - | N9 | place | house | 16 | Horiz St | - And the places - | osm | class | type | name | geometry | - | W1 | highway | residential | Vert St | 1,2 | - | W2 | highway | residential | Horiz St | 2,3 | - And the places - | osm | class | type | addr+interpolation | addr+inclusion | geometry | - | W10 | place | houses | even | actual | 8,9 | - And the ways - | id | nodes | - | 10 | 8,9 | - When importing - Then placex contains - | object | parent_place_id | - | N8 | W2 | - | N9 | W2 | - And W10 expands to interpolation - | start | end | parent_place_id | - | 12 | 14 | W2 | - - - Scenario Outline: Bad interpolation values are ignored - Given the grid with origin 1,1 - | 1 | | 9 | | 2 | - | 4 | | | | 5 | - Given the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 6 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | | 1,2 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 4,5 | - And the ways - | id | nodes | - | 1 | 1,2 | - When importing - Then W1 expands to no interpolation - - Examples: - | value | - | foo | - | x | - | 12-2 | - - - Scenario: Interpolation line where points have been moved (Github #3022) - Given the 0.00001 grid - | 1 | | | | | | | | 2 | 3 | 9 | | | | | | | | 4 | - Given the places - | osm | class | type | housenr | geometry | - | N1 | place | house | 2 | 1 | - | N2 | place | house | 18 | 3 | - | N3 | place | house | 24 | 9 | - | N4 | place | house | 42 | 4 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 1,2,3,4 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 1,4 | - And the ways - | id | nodes | - | 1 | 1,2,3,4 | - When importing - Then W1 expands to interpolation - | start | end | - | 4 | 16 | - | 20 | 22 | - | 26 | 40 | - - - Scenario: Interpolation line with duplicated points - Given the grid - | 7 | 10 | 8 | 11 | 9 | - | 4 | | | | 5 | - Given the places - | osm | class | type | housenr | geometry | - | N1 | place | house | 2 | 7 | - | N2 | place | house | 6 | 8 | - | N3 | place | house | 10 | 8 | - | N4 | place | house | 14 | 9 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 7,8,8,9 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 4,5 | - And the ways - | id | nodes | - | 1 | 1,2,3,4 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 4 | 4 | 10 | - | 12 | 12 | 11 | - - - Scenario: Interpolaton line with broken way geometry (Github #2986) - Given the grid - | 1 | 8 | 10 | 11 | 9 | 2 | 3 | 4 | - Given the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 8 | - | N3 | place | house | 12 | - | N4 | place | house | 14 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 8,9 | - And the named places - | osm | class | type | geometry | - | W10 | highway | residential | 1,4 | - And the ways - | id | nodes | - | 1 | 1,8,9,2,3,4 | - When importing - Then W1 expands to interpolation - | start | end | geometry | - | 4 | 6 | 10,11 | diff --git a/test/bdd/db/import/linking.feature b/test/bdd/db/import/linking.feature deleted file mode 100644 index 7997746e..00000000 --- a/test/bdd/db/import/linking.feature +++ /dev/null @@ -1,331 +0,0 @@ -@DB -Feature: Linking of places - Tests for correctly determining linked places - - Scenario: Only address-describing places can be linked - Given the grid - | 1 | | | | 2 | - | | | 9 | | | - | 4 | | | | 3 | - And the places - | osm | class | type | name | geometry | - | R13 | landuse | forest | Garbo | (1,2,3,4,1) | - | N256 | natural | peak | Garbo | 9 | - When importing - Then placex contains - | object | linked_place_id | - | R13 | - | - | N256 | - | - - Scenario: Postcode areas cannot be linked - Given the grid with origin US - | 1 | | 2 | - | | 9 | | - | 4 | | 3 | - And the named places - | osm | class | type | addr+postcode | extra+wikidata | geometry | - | R13 | boundary | postal_code | 12345 | Q87493 | (1,2,3,4,1) | - | N25 | place | suburb | 12345 | Q87493 | 9 | - When importing - Then placex contains - | object | linked_place_id | - | R13 | - | - | N25 | - | - - Scenario: Waterways are linked when in waterway relations - Given the grid - | 1 | | | | 3 | 4 | | | | 6 | - | | | 2 | | | 10 | | 5 | | | - | | | | | | 11 | | | | | - And the places - | osm | class | type | name | geometry | - | W1 | waterway | river | Rhein | 1,2,3 | - | W2 | waterway | river | Rhein | 3,4,5 | - | R13 | waterway | river | Rhein | 1,2,3,4,5,6 | - | R23 | waterway | river | Limmat| 4,10,11 | - And the relations - | id | members | tags+type | - | 13 | R23:tributary,W1,W2:main_stream | waterway | - When importing - Then placex contains - | object | linked_place_id | - | W1 | R13 | - | W2 | R13 | - | R13 | - | - | R23 | - | - When sending search query "rhein" - Then results contain - | osm | - | R13 | - - Scenario: Relations are not linked when in waterway relations - Given the grid - | 1 | | | | 3 | 4 | | | | 6 | - | | | 2 | | | 10 | | 5 | | | - | | | | | | 11 | | | | | - And the places - | osm | class | type | name | geometry | - | W1 | waterway | stream | Rhein | 1,2,3,4 | - | W2 | waterway | river | Rhein | 4,5,6 | - | R1 | waterway | river | Rhein | 1,2,3,4 | - | R2 | waterway | river | Limmat| 4,10,11 | - And the relations - | id | members | tags+type | - | 1 | R2 | waterway | - When importing - Then placex contains - | object | linked_place_id | - | W1 | - | - | W2 | - | - | R1 | - | - | R2 | - | - When sending search query "rhein" - Then results contain - | ID | osm | - | 0 | R1 | - | 1 | W2 | - - - Scenario: Empty waterway relations are handled correctly - Given the grid - | 1 | | | | 3 | - And the places - | osm | class | type | name | geometry | - | R1 | waterway | river | Rhein | 1,3 | - And the relations - | id | members | tags+type | - | 1 | | waterway | - When importing - Then placex contains - | object | linked_place_id | - | R1 | - | - - Scenario: Waterways are not linked when the way type is not a river feature - Given the grid - | 1 | | 2 | - | | | | - | 3 | | 4 | - And the places - | osm | class | type | name | geometry | - | W1 | waterway | lock | Rhein | 3,4 | - | R1 | landuse | meadow | Rhein | (3,1,2,4,3) | - And the relations - | id | members | tags+type | - | 1 | W1,W2 | multipolygon | - When importing - Then placex contains - | object | linked_place_id | - | W1 | - | - | R1 | - | - - Scenario: Side streams are linked only when they have the same name - Given the grid - | | | | | 8 | | | | - | 1 | | 2 | 3 | | 4 | 5 | 6| - | | | | | | 9 | | | - And the places - | osm | class | type | name | geometry | - | W1 | waterway | river | Rhein2 | 2,8,4 | - | W2 | waterway | river | Rhein | 3,9,5 | - | R1 | waterway | river | Rhein | 1,2,3,4,5,6 | - And the relations - | id | members | tags+type | - | 1 | W1:side_stream,W2:side_stream,W3 | waterway | - When importing - Then placex contains - | object | linked_place_id | - | W1 | - | - | W2 | R1 | - When sending search query "rhein2" - Then results contain - | osm | - | W1 | - - # github #573 - Scenario: Boundaries should only be linked to places - Given the 0.05 grid - | 1 | | 2 | - | | 9 | | - | 4 | | 3 | - Given the named places - | osm | class | type | extra+wikidata | admin | geometry | - | R1 | boundary | administrative | 34 | 8 | (1,2,3,4,1) | - And the named places - | osm | class | type | - | N9 | natural | island | - | N9 | place | city | - And the relations - | id | members | - | 1 | N9:label | - When importing - Then placex contains - | object | linked_place_id | - | N9:natural | - | - | N9:place | R1 | - - Scenario: Nodes with 'role' label are always linked - Given the 0.05 grid - | 1 | | 2 | - | | 9 | | - | 4 | | 3 | - Given the places - | osm | class | type | admin | name | geometry | - | R13 | boundary | administrative | 6 | Garbo | (1,2,3,4,1) | - | N2 | place | hamlet | 15 | Vario | 9 | - And the relations - | id | members | tags+type | - | 13 | N2:label | boundary | - When importing - Then placex contains - | object | linked_place_id | - | N2 | R13 | - And placex contains - | object | centroid | name+name | extratags+linked_place | - | R13 | 9 | Garbo | hamlet | - - Scenario: Boundaries with place tags are linked against places with same type - Given the 0.01 grid - | 1 | | 2 | - | | 9 | | - | 4 | | 3 | - Given the places - | osm | class | type | admin | name | extra+place | geometry | - | R13 | boundary | administrative | 4 | Berlin | city | (1,2,3,4,1) | - And the places - | osm | class | type | name | geometry | - | N2 | place | city | Berlin | 9 | - When importing - Then placex contains - | object | linked_place_id | - | N2 | R13 | - And placex contains - | object | rank_address | - | R13 | 16 | - When sending search query "" - | city | - | Berlin | - Then results contain - | ID | osm | - | 0 | R13 | - When sending search query "" - | state | - | Berlin | - Then results contain - | ID | osm | - | 0 | R13 | - - - Scenario: Boundaries without place tags only link against same admin level - Given the 0.05 grid - | 1 | | 2 | - | | 9 | | - | 4 | | 3 | - Given the places - | osm | class | type | admin | name | geometry | - | R13 | boundary | administrative | 4 | Berlin | (1,2,3,4,1) | - And the places - | osm | class | type | name | geometry | - | N2 | place | city | Berlin | 9 | - When importing - Then placex contains - | object | linked_place_id | - | N2 | - | - And placex contains - | object | rank_address | - | R13 | 8 | - When sending search query "" - | state | - | Berlin | - Then results contain - | ID | osm | - | 0 | R13 | - When sending search query "" - | city | - | Berlin | - Then results contain - | ID | osm | - | 0 | N2 | - - # github #1352 - Scenario: Do not use linked centroid when it is outside the area - Given the 0.05 grid - | 1 | | 2 | | - | | | | 9 | - | 4 | | 3 | | - Given the named places - | osm | class | type | admin | geometry | - | R13 | boundary | administrative | 4 | (1,2,3,4,1) | - And the named places - | osm | class | type | geometry | - | N2 | place | city | 9 | - And the relations - | id | members | tags+type | - | 13 | N2:label | boundary | - When importing - Then placex contains - | object | linked_place_id | - | N2 | R13 | - And placex contains - | object | centroid | - | R13 | in geometry | - - Scenario: Place nodes can only be linked once - Given the 0.02 grid - | 1 | | 2 | | 5 | - | | 9 | | | | - | 4 | | 3 | | 6 | - Given the named places - | osm | class | type | extra+wikidata | geometry | - | N2 | place | city | Q1234 | 9 | - And the named places - | osm | class | type | extra+wikidata | admin | geometry | - | R1 | boundary | administrative | Q1234 | 8 | (1,2,5,6,3,4,1) | - | R2 | boundary | administrative | Q1234 | 9 | (1,2,3,4,1) | - When importing - Then placex contains - | object | linked_place_id | - | N2 | R1 | - And placex contains - | object | extratags | - | R1 | 'linked_place' : 'city', 'wikidata': 'Q1234' | - | R2 | 'wikidata': 'Q1234' | - - - Scenario: Boundaries without names inherit names from linked places - Given the 0.05 grid - | 1 | | 2 | - | | 9 | | - | 4 | | 3 | - Given the places - | osm | class | type | extra+wikidata | admin | geometry | - | R1 | boundary | administrative | 34 | 8 | (1,2,3,4,1) | - And the places - | osm | class | type | name+name | - | N9 | place | city | LabelPlace | - And the relations - | id | members | - | 1 | N9:label | - When importing - Then placex contains - | object | name+_place_name | - | R1 | LabelPlace | - - - @Fail - Scenario: Linked places expand default language names - Given the grid - | 1 | | 2 | - | | 9 | | - | 4 | | 3 | - Given the places - | osm | class | type | name+name | geometry | - | N9 | place | city | Popayán | 9 | - | R1 | boundary | administrative | Perímetro Urbano Popayán | (1,2,3,4,1) | - And the relations - | id | members | - | 1 | N9:label | - When importing - Then placex contains - | object | name+_place_name | name+_place_name:es | - | R1 | Popayán | Popayán | - diff --git a/test/bdd/db/import/naming.feature b/test/bdd/db/import/naming.feature deleted file mode 100644 index b739cbae..00000000 --- a/test/bdd/db/import/naming.feature +++ /dev/null @@ -1,105 +0,0 @@ -@DB -Feature: Import and search of names - Tests all naming related import issues - - Scenario: No copying name tag if only one name - Given the places - | osm | class | type | name | geometry | - | N1 | place | locality | german | country:de | - When importing - Then placex contains - | object | country_code | name+name | - | N1 | de | german | - - Scenario: Copying name tag to default language if it does not exist - Given the places - | osm | class | type | name | name+name:fi | geometry | - | N1 | place | locality | german | finnish | country:de | - When importing - Then placex contains - | object | country_code | name | name+name:fi | name+name:de | - | N1 | de | german | finnish | german | - - Scenario: Copying default language name tag to name if it does not exist - Given the places - | osm | class | type | name+name:de | name+name:fi | geometry | - | N1 | place | locality | german | finnish | country:de | - When importing - Then placex contains - | object | country_code | name | name+name:fi | name+name:de | - | N1 | de | german | finnish | german | - - Scenario: Do not overwrite default language with name tag - Given the places - | osm | class | type | name | name+name:fi | name+name:de | geometry | - | N1 | place | locality | german | finnish | local | country:de | - When importing - Then placex contains - | object | country_code | name | name+name:fi | name+name:de | - | N1 | de | german | finnish | local | - - Scenario Outline: Names in any script can be found - Given the places - | osm | class | type | name | - | N1 | place | hamlet | | - When importing - And sending search query "" - Then results contain - | osm | - | N1 | - - Examples: - | name | - | Berlin | - | 北京 | - | Вологда | - | Αθήνα | - | القاهرة | - | រាជធានីភ្នំពេញ | - | 東京都 | - | ပုဗ္ဗသီရိ | - - - Scenario: German umlauts can be found when expanded - Given the places - | osm | class | type | name+name:de | - | N1 | place | city | Münster | - | N2 | place | city | Köln | - | N3 | place | city | Gräfenroda | - When importing - When sending search query "münster" - Then results contain - | osm | - | N1 | - When sending search query "muenster" - Then results contain - | osm | - | N1 | - When sending search query "munster" - Then results contain - | osm | - | N1 | - When sending search query "Köln" - Then results contain - | osm | - | N2 | - When sending search query "Koeln" - Then results contain - | osm | - | N2 | - When sending search query "Koln" - Then results contain - | osm | - | N2 | - When sending search query "gräfenroda" - Then results contain - | osm | - | N3 | - When sending search query "graefenroda" - Then results contain - | osm | - | N3 | - When sending search query "grafenroda" - Then results contain - | osm | - | N3 | diff --git a/test/bdd/db/import/parenting.feature b/test/bdd/db/import/parenting.feature deleted file mode 100644 index 55fa6a60..00000000 --- a/test/bdd/db/import/parenting.feature +++ /dev/null @@ -1,652 +0,0 @@ -@DB -Feature: Parenting of objects - Tests that the correct parent is chosen - - Scenario: Address inherits postcode from its street unless it has a postcode - Given the grid with origin DE - | 10 | | | | | 11 | - | | | | | | | - | | 1 | | 2 | | | - And the places - | osm | class | type | housenr | - | N1 | place | house | 4 | - And the places - | osm | class | type | housenr | postcode | - | N2 | place | house | 5 | 99999 | - And the places - | osm | class | type | name | postcode | geometry | - | W1 | highway | residential | galoo | 12345 | 10,11 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W1 | - | N2 | W1 | - When sending search query "4 galoo" - Then results contain - | ID | osm | display_name | - | 0 | N1 | 4, galoo, 12345, Deutschland | - When sending search query "5 galoo" - Then results contain - | ID | osm | display_name | - | 0 | N2 | 5, galoo, 99999, Deutschland | - - Scenario: Address without tags, closest street - Given the grid - | 10 | | | | | 11 | - | | 1 | 2 | | | | - | | | | 3 | 4 | | - | 20 | | | | | 21 | - And the places - | osm | class | type | - | N1 | place | house | - | N2 | place | house | - | N3 | place | house | - | N4 | place | house | - And the named places - | osm | class | type | geometry | - | W1 | highway | residential | 10,11 | - | W2 | highway | residential | 20,21 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W1 | - | N2 | W1 | - | N3 | W2 | - | N4 | W2 | - - Scenario: Address without tags avoids unnamed streets - Given the grid - | 10 | | | | | 11 | - | | 1 | 2 | | | | - | | | | 3 | 4 | | - | 20 | | | | | 21 | - And the places - | osm | class | type | - | N1 | place | house | - | N2 | place | house | - | N3 | place | house | - | N4 | place | house | - And the places - | osm | class | type | geometry | - | W1 | highway | residential | 10,11 | - And the named places - | osm | class | type | geometry | - | W2 | highway | residential | 20,21 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W2 | - | N2 | W2 | - | N3 | W2 | - | N4 | W2 | - - Scenario: addr:street tag parents to appropriately named street - Given the grid - | 10 | | | | | 11 | - | | 1 | 2 | | | | - | | | | 3 | 4 | | - | 20 | | | | | 21 | - And the places - | osm | class | type | street| - | N1 | place | house | south | - | N2 | place | house | north | - | N3 | place | house | south | - | N4 | place | house | north | - And the places - | osm | class | type | name | geometry | - | W1 | highway | residential | north | 10,11 | - | W2 | highway | residential | south | 20,21 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W2 | - | N2 | W1 | - | N3 | W2 | - | N4 | W1 | - - Scenario: addr:street tag parents to appropriately named street, locale names - Given the grid - | 10 | | | | | 11 | - | | 1 | 2 | | | | - | | | | 3 | 4 | | - | 20 | | | | | 21 | - And the places - | osm | class | type | street| addr+street:de | - | N1 | place | house | south | Süd | - | N2 | place | house | north | Nord | - | N3 | place | house | south | Süd | - | N4 | place | house | north | Nord | - And the places - | osm | class | type | name | geometry | - | W1 | highway | residential | Nord | 10,11 | - | W2 | highway | residential | Süd | 20,21 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W2 | - | N2 | W1 | - | N3 | W2 | - | N4 | W1 | - - Scenario: addr:street tag parents to appropriately named street with abbreviation - Given the grid - | 10 | | | | | 11 | - | | 1 | 2 | | | | - | | | | 3 | 4 | | - | 20 | | | | | 21 | - And the places - | osm | class | type | street | - | N1 | place | house | south st | - | N2 | place | house | north st | - | N3 | place | house | south st | - | N4 | place | house | north st | - And the places - | osm | class | type | name+name:en | geometry | - | W1 | highway | residential | north street | 10,11 | - | W2 | highway | residential | south street | 20,21 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W2 | - | N2 | W1 | - | N3 | W2 | - | N4 | W1 | - - Scenario: addr:street tag parents to next named street - Given the grid - | 10 | | | | | 11 | - | | 1 | 2 | | | | - | | | | 3 | 4 | | - | 20 | | | | | 21 | - And the places - | osm | class | type | street | - | N1 | place | house | abcdef | - | N2 | place | house | abcdef | - | N3 | place | house | abcdef | - | N4 | place | house | abcdef | - And the places - | osm | class | type | name | geometry | - | W1 | highway | residential | abcdef | 10,11 | - | W2 | highway | residential | abcdef | 20,21 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W1 | - | N2 | W1 | - | N3 | W2 | - | N4 | W2 | - - Scenario: addr:street tag without appropriately named street - Given the grid - | 10 | | | | | 11 | - | | 1 | | | | | - | | | | 3 | | | - | 20 | | | | | 21 | - And the places - | osm | class | type | street | - | N1 | place | house | abcdef | - | N3 | place | house | abcdef | - And the places - | osm | class | type | name | geometry | - | W1 | highway | residential | abcde | 10,11 | - | W2 | highway | residential | abcde | 20,21 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W1 | - | N3 | W2 | - - Scenario: addr:place address - Given the grid - | 10 | | | | - | | 1 | | 2 | - | 11 | | | | - And the places - | osm | class | type | addr_place | - | N1 | place | house | myhamlet | - And the places - | osm | class | type | name | geometry | - | N2 | place | hamlet | myhamlet | 2 | - | W1 | highway | residential | myhamlet | 10,11 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | N2 | - - Scenario: addr:street is preferred over addr:place - Given the grid - | 10 | | | | - | | | 1 | 2 | - | 11 | | | | - And the places - | osm | class | type | addr_place | street | - | N1 | place | house | myhamlet | mystreet| - And the places - | osm | class | type | name | geometry | - | N2 | place | hamlet | myhamlet | 2 | - | W1 | highway | residential | mystreet | 10,11 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W1 | - - Scenario: Untagged address in simple associated street relation - Given the grid - | 10 | | | | | 11 | - | | 2 | | 3 | | | - | | | | | | | - | 12 | 1 | | | | | - And the places - | osm | class | type | - | N1 | place | house | - | N2 | place | house | - | N3 | place | house | - And the places - | osm | class | type | name | geometry | - | W1 | highway | residential | foo | 10,11 | - | W2 | highway | service | bar | 10,12 | - And the relations - | id | members | tags+type | - | 1 | W1:street,N1,N2,N3 | associatedStreet | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W1 | - | N2 | W1 | - | N3 | W1 | - - Scenario: Avoid unnamed streets in simple associated street relation - Given the grid - | 10 | | | | | 11 | - | | 2 | | 3 | | | - | | | | | | | - | 12 | 1 | | | | | - And the places - | osm | class | type | - | N1 | place | house | - | N2 | place | house | - | N3 | place | house | - And the places - | osm | class | type | geometry | - | W2 | highway | residential | 10,12 | - And the named places - | osm | class | type | geometry | - | W1 | highway | residential | 10,11 | - And the relations - | id | members | tags+type | - | 1 | N1,N2,N3,W2:street,W1:street | associatedStreet | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W1 | - | N2 | W1 | - | N3 | W1 | - - Scenario: Associated street relation overrides addr:street - Given the grid - | 10 | | | | 11 | - | | | | | | - | | | 1 | | | - | | 20 | | 21 | | - And the places - | osm | class | type | street | - | N1 | place | house | bar | - And the places - | osm | class | type | name | geometry | - | W1 | highway | residential | foo | 10,11 | - | W2 | highway | residential | bar | 20,21 | - And the relations - | id | members | tags+type | - | 1 | W1:street,N1 | associatedStreet | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W1 | - - Scenario: Building without tags, closest street from center point - Given the grid - | 10 | | | | 11 | - | | | 1 | 2 | | - | 12 | | 4 | 3 | | - And the named places - | osm | class | type | geometry | - | W1 | building | yes | (1,2,3,4,1) | - | W2 | highway | primary | 10,11 | - | W3 | highway | residential | 10,12 | - When importing - Then placex contains - | object | parent_place_id | - | W1 | W2 | - - Scenario: Building with addr:street tags - Given the grid - | 10 | | | | 11 | - | | | 1 | 2 | | - | 12 | | 4 | 3 | | - And the named places - | osm | class | type | street | geometry | - | W1 | building | yes | foo | (1,2,3,4,1) | - And the places - | osm | class | type | name | geometry | - | W2 | highway | primary | bar | 10,11 | - | W3 | highway | residential | foo | 10,12 | - When importing - Then placex contains - | object | parent_place_id | - | W1 | W3 | - - Scenario: Building with addr:place tags - Given the grid - | 10 | | | | | - | | 1 | 2 | | 9 | - | 11 | 4 | 3 | | | - And the places - | osm | class | type | name | geometry | - | N9 | place | village | bar | 9 | - | W2 | highway | primary | bar | 10,11 | - And the named places - | osm | class | type | addr_place | geometry | - | W1 | building | yes | bar | (1,2,3,4,1) | - When importing - Then placex contains - | object | parent_place_id | - | W1 | N9 | - - Scenario: Building in associated street relation - Given the grid - | 10 | | | | 11 | - | | | 1 | 2 | | - | 12 | | 4 | 3 | | - And the named places - | osm | class | type | geometry | - | W1 | building | yes | (1,2,3,4,1) | - And the places - | osm | class | type | name | geometry | - | W2 | highway | primary | bar | 10,11 | - | W3 | highway | residential | foo | 10,12 | - And the relations - | id | members | tags+type | - | 1 | W1:house,W3:street | associatedStreet | - When importing - Then placex contains - | object | parent_place_id | - | W1 | W3 | - - Scenario: Building in associated street relation overrides addr:street - Given the grid - | 10 | | | | 11 | - | | | 1 | 2 | | - | 12 | | 4 | 3 | | - And the named places - | osm | class | type | street | geometry | - | W1 | building | yes | foo | (1,2,3,4,1) | - And the places - | osm | class | type | name | geometry | - | W2 | highway | primary | bar | 10,11 | - | W3 | highway | residential | foo | 10,12 | - And the relations - | id | members | tags+type | - | 1 | W1:house,W2:street | associatedStreet | - When importing - Then placex contains - | object | parent_place_id | - | W1 | W2 | - - Scenario: Wrong member in associated street relation is ignored - Given the grid - | 10 | | | | | | | 11 | - | | 1 | | 3 | 4 | | | | - | | | | 6 | 5 | | | | - And the named places - | osm | class | type | geometry | - | N1 | place | house | 11 | - And the named places - | osm | class | type | street | geometry | - | W1 | building | yes | foo | (3,4,5,6,3) | - And the places - | osm | class | type | name | geometry | - | W3 | highway | residential | foo | 10,11 | - And the relations - | id | members | tags+type | - | 1 | N1:house,W1:street,W3:street | associatedStreet | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W3 | - - Scenario: street member in associatedStreet relation can be a relation - Given the grid - | 1 | | | 2 | - | 3 | | | 4 | - | | | | | - | | 9 | | | - | 5 | | | 6 | - And the places - | osm | class | type | housenr | geometry | - | N9 | place | house | 34 | 9 | - And the named places - | osm | class | type | name | geometry | - | R14 | highway | pedestrian | Right St | (1,2,4,3,1) | - | W14 | highway | pedestrian | Left St | 5,6 | - And the relations - | id | members | tags+type | - | 1 | N9:house,R14:street | associatedStreet | - When importing - Then placex contains - | object | parent_place_id | - | N9 | R14 | - - - Scenario: Choose closest street in associatedStreet relation - Given the grid - | 1 | | | | 3 | - | 10 | | 11 | | 12 | - And the places - | osm | class | type | housenr | geometry | - | N1 | place | house | 1 | 1 | - | N3 | place | house | 3 | 3 | - And the named places - | osm | class | type | geometry | - | W100 | highway | residential | 10,11 | - | W101 | highway | residential | 11,12 | - And the relations - | id | members | tags+type | - | 1 | N1:house,N3:house,W100:street,W101:street | associatedStreet | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W100 | - | N3 | W101 | - - - Scenario: POIs in building inherit address - Given the grid - | 10 | | | | | | 11 | - | | | 5 | 2 | 6 | | | - | | | 3 | 1 | | | | - | 12 | | 8 | | 7 | | | - And the named places - | osm | class | type | - | N1 | amenity | bank | - | N2 | shop | bakery | - | N3 | shop | supermarket| - And the places - | osm | class | type | street | housenr | geometry | - | W1 | building | yes | foo | 3 | (5,6,7,8,5) | - And the places - | osm | class | type | name | geometry | - | W2 | highway | primary | bar | 10,11 | - | W3 | highway | residential | foo | 10,12 | - When importing - Then placex contains - | object | parent_place_id | housenumber | - | W1 | W3 | 3 | - | N1 | W3 | 3 | - | N2 | W3 | 3 | - | N3 | W3 | 3 | - When sending geocodejson search query "3, foo" with address - Then results contain - | housenumber | - | 3 | - - Scenario: POIs don't inherit from streets - Given the grid - | 10 | | | | 11 | - | | 5 | 1 | 6 | | - | | 8 | | 7 | | - And the named places - | osm | class | type | - | N1 | amenity | bank | - And the places - | osm | class | type | name | street | housenr | geometry | - | W1 | highway | path | bar | foo | 3 | (5,6,7,8,5) | - And the places - | osm | class | type | name | geometry | - | W3 | highway | residential | foo | 10,11 | - When importing - Then placex contains - | object | parent_place_id | housenumber | - | N1 | W1 | None | - - Scenario: POIs with own address do not inherit building address - Given the grid - | 10 | | | | | | 11 | - | | | 6 | 2 | 7 | | | - | | | 3 | 1 | | 5 | 4 | - | 12 | | 9 | | 8 | | | - And the named places - | osm | class | type | street | - | N1 | amenity | bank | bar | - And the named places - | osm | class | type | housenr | - | N2 | shop | bakery | 4 | - And the named places - | osm | class | type | addr_place | - | N3 | shop | supermarket| nowhere | - And the places - | osm | class | type | name | - | N4 | place | isolated_dwelling | theplace | - | N5 | place | isolated_dwelling | nowhere | - And the places - | osm | class | type | addr_place | housenr | geometry | - | W1 | building | yes | theplace | 3 | (6,7,8,9,6) | - And the places - | osm | class | type | name | geometry | - | W2 | highway | primary | bar | 10,11 | - | W3 | highway | residential | foo | 10,12 | - When importing - Then placex contains - | object | parent_place_id | housenumber | - | W1 | N4 | 3 | - | N1 | W2 | None | - | N2 | W2 | 4 | - | N3 | N5 | None | - - Scenario: POIs parent a road if they are attached to it - Given the grid - | | 10 | | - | 20 | 1 | 21 | - | | 11 | | - And the named places - | osm | class | type | - | N1 | highway | bus_stop | - And the places - | osm | class | type | name | geometry | - | W1 | highway | secondary | North St | 10,11 | - | W2 | highway | unclassified | South St | 20,1,21 | - And the ways - | id | nodes | - | 1 | 10,11 | - | 2 | 20,1,21 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W2 | - - Scenario: POIs do not parent non-roads they are attached to - Given the grid - | 10 | | 1 | | 11 | | 30 | - | 14 | | | | 15 | | | - | 13 | | 2 | | 12 | | 31 | - And the named places - | osm | class | type | street | - | N1 | highway | bus_stop | North St | - | N2 | highway | bus_stop | South St | - And the places - | osm | class | type | name | geometry | - | W1 | landuse | residential | North St | (14,15,12,2,13,14) | - | W2 | waterway| river | South St | 10,1,11 | - | W3 | highway | residential | foo | 30,31 | - And the ways - | id | nodes | - | 1 | 10,11,12,2,13,10 | - | 2 | 10,1,11 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W3 | - | N2 | W3 | - - Scenario: POIs on building outlines inherit associated street relation - Given the grid - | 10 | | | | 11 | - | | 5 | 1 | 6 | | - | 12 | 8 | | 7 | | - And the named places - | osm | class | type | geometry | - | N1 | place | house | 1 | - | W1 | building | yes | (5,1,6,7,8,5)| - And the places - | osm | class | type | name | geometry | - | W2 | highway | primary | bar | 10,11 | - | W3 | highway | residential | foo | 10,12 | - And the relations - | id | members | tags+type | - | 1 | W1:house,W3:street | associatedStreet | - And the ways - | id | nodes | - | 1 | 5,1,6,7,8,5 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W3 | - - # github #1056 - Scenario: Full names should be preferably matched for nearest road - Given the grid - | 1 | | 2 | 5 | - | | | | | - | 3 | | | 4 | - | | 10| | | - And the places - | osm | class | type | name+name | geometry | - | W1 | highway | residential | Via Cavassico superiore | 1, 2 | - | W3 | highway | residential | Via Cavassico superiore | 2, 5 | - | W2 | highway | primary | Via Frazione Cavassico | 3, 4 | - And the named places - | osm | class | type | addr+street | - | N10 | shop | yes | Via Cavassico superiore | - When importing - Then placex contains - | object | parent_place_id | - | N10 | W1 | - - Scenario: place=square may be parented via addr:place - Given the grid - | | | 9 | | | - | | 5 | | 6 | | - | | 8 | | 7 | | - And the places - | osm | class | type | name+name | geometry | - | W2 | place | square | Foo pl | (5, 6, 7, 8, 5) | - And the places - | osm | class | type | name+name | housenr | addr_place | geometry | - | N10 | shop | grocery | le shop | 5 | Foo pl | 9 | - When importing - Then placex contains - | object | rank_address | - | W2 | 25 | - Then placex contains - | object | parent_place_id | - | N10 | W2 | - diff --git a/test/bdd/db/import/placex.feature b/test/bdd/db/import/placex.feature deleted file mode 100644 index e0e8925f..00000000 --- a/test/bdd/db/import/placex.feature +++ /dev/null @@ -1,194 +0,0 @@ -@DB -Feature: Import into placex - Tests that data in placex is completed correctly. - - Scenario: No country code tag is available - Given the named places - | osm | class | type | geometry | - | N1 | highway | primary | country:us | - When importing - Then placex contains - | object | addr+country | country_code | - | N1 | - | us | - - Scenario: Location overwrites country code tag - Given the named places - | osm | class | type | country | geometry | - | N1 | highway | primary | de | country:us | - When importing - Then placex contains - | object | addr+country | country_code | - | N1 | de | us | - - Scenario: Country code tag overwrites location for countries - Given the named places - | osm | class | type | admin | country | geometry | - | R1 | boundary | administrative | 2 | de | (-100 40, -101 40, -101 41, -100 41, -100 40) | - When importing - Then placex contains - | object | rank_search| addr+country | country_code | - | R1 | 4 | de | de | - - Scenario: Illegal country code tag for countries is ignored - Given the named places - | osm | class | type | admin | country | geometry | - | R1 | boundary | administrative | 2 | xx | (-100 40, -101 40, -101 41, -100 41, -100 40) | - When importing - Then placex contains - | object | addr+country | country_code | - | R1 | xx | us | - - Scenario: admin level is copied over - Given the named places - | osm | class | type | admin | - | N1 | place | state | 3 | - When importing - Then placex contains - | object | admin_level | - | N1 | 3 | - - Scenario: postcode node without postcode is dropped - Given the places - | osm | class | type | name+ref | - | N1 | place | postcode | 12334 | - When importing - Then placex has no entry for N1 - - Scenario: postcode boundary without postcode is dropped - Given the 0.01 grid - | 1 | 2 | - | 3 | | - Given the places - | osm | class | type | name+ref | geometry | - | R1 | boundary | postal_code | 554476 | (1,2,3,1) | - When importing - Then placex has no entry for R1 - - Scenario: search and address ranks for boundaries are correctly assigned - Given the named places - | osm | class | type | - | N1 | boundary | administrative | - And the named places - | osm | class | type | geometry | - | W10 | boundary | administrative | 10 10, 11 11 | - And the named places - | osm | class | type | admin | geometry | - | R20 | boundary | administrative | 2 | (1 1, 2 2, 1 2, 1 1) | - | R21 | boundary | administrative | 32 | (3 3, 4 4, 3 4, 3 3) | - | R22 | boundary | nature_park | 6 | (0 0, 1 0, 0 1, 0 0) | - | R23 | boundary | natural_reserve| 10 | (0 0, 1 1, 1 0, 0 0) | - And the named places - | osm | class | type | geometry | - | R40 | place | country | (1 1, 2 2, 1 2, 1 1) | - | R41 | place | state | (3 3, 4 4, 3 4, 3 3) | - When importing - Then placex has no entry for N1 - And placex has no entry for W10 - And placex contains - | object | rank_search | rank_address | - | R20 | 4 | 4 | - | R21 | 25 | 0 | - | R22 | 25 | 0 | - | R23 | 25 | 0 | - | R40 | 4 | 0 | - | R41 | 8 | 0 | - - Scenario: search and address ranks for highways correctly assigned - Given the grid - | 10 | 1 | 11 | | 12 | | 13 | | 14 | | 15 | | 16 | - And the places - | osm | class | type | - | N1 | highway | bus_stop | - And the places - | osm | class | type | geometry | - | W1 | highway | primary | 10,11 | - | W2 | highway | secondary | 11,12 | - | W3 | highway | tertiary | 12,13 | - | W4 | highway | residential | 13,14 | - | W5 | highway | unclassified | 14,15 | - | W6 | highway | something | 15,16 | - When importing - Then placex contains - | object | rank_search | rank_address | - | N1 | 30 | 30 | - | W1 | 26 | 26 | - | W2 | 26 | 26 | - | W3 | 26 | 26 | - | W4 | 26 | 26 | - | W5 | 26 | 26 | - | W6 | 30 | 30 | - - Scenario: rank and inclusion of landuses - Given the 0.4 grid - | 1 | 2 | | | | | | 5 | - | 4 | 3 | | | | | | 6 | - Given the named places - | osm | class | type | - | N2 | landuse | residential | - And the named places - | osm | class | type | geometry | - | W2 | landuse | residential | 1,2,5 | - | W4 | landuse | residential | (1,4,3,1) | - | R2 | landuse | residential | (1,2,3,4,1) | - | R3 | landuse | forrest | (1,5,6,4,1) | - When importing - Then placex contains - | object | rank_search | rank_address | - | N2 | 30 | 30 | - | W2 | 30 | 30 | - | W4 | 22 | 22 | - | R2 | 22 | 22 | - | R3 | 22 | 0 | - - Scenario: rank and inclusion of naturals - Given the 0.4 grid - | 1 | 2 | | | | | | 5 | - | 4 | 3 | | | | | | 6 | - Given the named places - | osm | class | type | - | N2 | natural | peak | - | N4 | natural | volcano | - | N5 | natural | foobar | - And the named places - | osm | class | type | geometry | - | W2 | natural | mountain_range | 1,2,5 | - | W3 | natural | foobar | 2,3 | - | R3 | natural | volcano | (1,2,4,1) | - | R4 | natural | foobar | (1,2,3,4,1) | - | R5 | natural | sea | (1,2,5,6,3,4,1) | - | R6 | natural | sea | (2,3,4,2) | - When importing - Then placex contains - | object | rank_search | rank_address | - | N2 | 18 | 0 | - | N4 | 18 | 0 | - | N5 | 22 | 0 | - | W2 | 18 | 0 | - | R3 | 18 | 0 | - | R4 | 22 | 0 | - | R5 | 4 | 0 | - | R6 | 4 | 0 | - | W3 | 22 | 0 | - - Scenario: boundary ways for countries and states are ignored - Given the 0.3 grid - | 1 | 2 | - | 4 | 3 | - Given the named places - | osm | class | type | admin | geometry | - | W4 | boundary | administrative | 2 | (1,2,3,4,1) | - | R4 | boundary | administrative | 2 | (1,2,3,4,1) | - | W5 | boundary | administrative | 3 | (1,2,3,4,1) | - | R5 | boundary | administrative | 3 | (1,2,3,4,1) | - | W6 | boundary | administrative | 4 | (1,2,3,4,1) | - | R6 | boundary | administrative | 4 | (1,2,3,4,1) | - | W7 | boundary | administrative | 5 | (1,2,3,4,1) | - | R7 | boundary | administrative | 5 | (1,2,3,4,1) | - When importing - Then placex contains exactly - | object | - | R4 | - | R5 | - | R6 | - | W7 | - | R7 | diff --git a/test/bdd/db/import/postcodes.feature b/test/bdd/db/import/postcodes.feature deleted file mode 100644 index a9b07bfe..00000000 --- a/test/bdd/db/import/postcodes.feature +++ /dev/null @@ -1,210 +0,0 @@ -@DB -Feature: Import of postcodes - Tests for postcode estimation - - Scenario: Postcodes on the object are preferred over those on the address - Given the grid with origin FR - | 1 | | | | 4 | | 6 | | 8 | - | | 10 | | 11 | | | | | | - | | | 22 | | | | | | | - | 2 | | | | 3 | | 5 | | 7 | - And the named places - | osm | class | type | admin | addr+postcode | geometry | - | R1 | boundary | administrative | 6 | 10000 | (1,8,7,2,1) | - | R34 | boundary | administrative | 8 | 11000 | (1,6,5,2,1) | - | R4 | boundary | administrative | 10 | 11200 | (1,4,3,2,1) | - And the named places - | osm | class | type | addr+postcode | geometry | - | W93 | highway | residential | 11250 | 10,11 | - | N22 | building | yes | 11254 | 22 | - When importing - Then placex contains - | object | postcode | - | N22 | 11254 | - | W93 | 11250 | - | R4 | 11200 | - | R34 | 11000 | - | R1 | 10000 | - - Scenario: Postcodes from a road are inherited by an attached building - Given the grid with origin DE - | 10 | | | | 11 | - | | 1 | 2 | | | - | | 4 | 3 | | | - And the named places - | osm | class | type | addr+postcode | geometry | - | W93 | highway | residential | 86034 | 10,11 | - And the named places - | osm | class | type | geometry | - | W22 | building | yes | (1,2,3,4,1) | - When importing - Then placex contains - | object | postcode | parent_place_id | - | W22 | 86034 | W93 | - - Scenario: Postcodes from the lowest admin area are inherited by ways - Given the grid with origin FR - | 1 | | | | 4 | | 6 | | 8 | - | | 10 | | 11 | | | | | | - | 2 | | | | 3 | | 5 | | 7 | - And the named places - | osm | class | type | admin | addr+postcode | geometry | - | R1 | boundary | administrative | 6 | 10000 | (1,8,7,2,1) | - | R34 | boundary | administrative | 8 | 11000 | (1,6,5,2,1) | - | R4 | boundary | administrative | 10 | 11200 | (1,4,3,2,1) | - And the named places - | osm | class | type | geometry | - | W93 | highway | residential | 10,11 | - When importing - Then placex contains - | object | postcode | - | W93 | 11200 | - - Scenario: Postcodes from the lowest admin area with postcode are inherited by ways - Given the grid with origin FR - | 1 | | | | 4 | | 6 | | 8 | - | | 10 | | 11 | | | | | | - | 2 | | | | 3 | | 5 | | 7 | - And the named places - | osm | class | type | admin | addr+postcode | geometry | - | R1 | boundary | administrative | 6 | 10000 | (1,8,7,2,1) | - | R34 | boundary | administrative | 8 | 11000 | (1,6,5,2,1) | - And the named places - | osm | class | type | admin | geometry | - | R4 | boundary | administrative | 10 | (1,4,3,2,1) | - And the named places - | osm | class | type | geometry | - | W93 | highway | residential | 10,11 | - When importing - Then placex contains - | object | postcode | parent_place_id | - | W93 | 11000 | R4 | - - Scenario: Postcodes from the lowest admin area are inherited by buildings - Given the grid with origin FR - | 1 | | | | 4 | | 6 | | 8 | - | | 10 | | 11 | | | | | | - | | 13 | | 12 | | | | | | - | 2 | | | | 3 | | 5 | | 7 | - And the named places - | osm | class | type | admin | addr+postcode | geometry | - | R1 | boundary | administrative | 6 | 10000 | (1,8,7,2,1) | - | R34 | boundary | administrative | 8 | 11000 | (1,6,5,2,1) | - | R4 | boundary | administrative | 10 | 11200 | (1,4,3,2,1) | - And the named places - | osm | class | type | geometry | - | W22 | building | yes | (10,11,12,13,10) | - When importing - Then placex contains - | object | postcode | - | W22 | 11200 | - - Scenario: Roads get postcodes from nearby named buildings without other info - Given the grid with origin US - | 10 | | | | 11 | - | | 1 | 2 | | | - | | 4 | 3 | | | - And the named places - | osm | class | type | geometry | - | W93 | highway | residential | 10,11 | - And the named places - | osm | class | type | addr+postcode | geometry | - | W22 | building | yes | 45023 | (1,2,3,4,1) | - When importing - Then placex contains - | object | postcode | - | W93 | 45023 | - - Scenario: Road areas get postcodes from nearby named buildings without other info - Given the grid with origin US - | 10 | | | | 11 | - | 13 | | | | 12 | - | | 1 | 2 | | | - | | 4 | 3 | | | - And the named places - | osm | class | type | geometry | - | W93 | highway | pedestriant | (10,11,12,13,10) | - And the named places - | osm | class | type | addr+postcode | geometry | - | W22 | building | yes | 45023 | (1,2,3,4,1) | - When importing - Then placex contains - | object | postcode | - | W93 | 45023 | - - Scenario: Roads get postcodes from nearby unnamed buildings without other info - Given the grid with origin US - | 10 | | | | 11 | - | | 1 | 2 | | | - | | 4 | 3 | | | - And the named places - | osm | class | type | geometry | - | W93 | highway | residential | 10,11 | - And the places - | osm | class | type | addr+postcode | geometry | - | W22 | place | postcode | 45023 | (1,2,3,4,1) | - When importing - Then placex contains - | object | postcode | - | W93 | 45023 | - - Scenario: Postcodes from admin boundaries are preferred over estimated postcodes - Given the grid with origin FR - | 1 | | | | 4 | | 6 | | 8 | - | | 10 | | 11 | | | | | | - | | | 22 | | | | | | | - | 2 | | | | 3 | | 5 | | 7 | - And the named places - | osm | class | type | admin | addr+postcode | geometry | - | R1 | boundary | administrative | 6 | 10000 | (1,8,7,2,1) | - | R34 | boundary | administrative | 8 | 11000 | (1,6,5,2,1) | - | R4 | boundary | administrative | 10 | 11200 | (1,4,3,2,1) | - And the named places - | osm | class | type | geometry | - | W93 | highway | residential | 10,1 | - And the named places - | osm | class | type | addr+postcode | - | N22 | building | yes | 45023 | - When importing - Then placex contains - | object | postcode | - | W93 | 11200 | - - Scenario: Postcodes are added to the postcode - Given the places - | osm | class | type | addr+postcode | addr+housenumber | geometry | - | N34 | place | house | 01982 | 111 |country:de | - When importing - Then location_postcode contains exactly - | country | postcode | geometry | - | de | 01982 | country:de | - - - @Fail - Scenario: search and address ranks for GB post codes correctly assigned - Given the places - | osm | class | type | postcode | geometry | - | N1 | place | postcode | E45 2CD | country:gb | - | N2 | place | postcode | E45 2 | country:gb | - | N3 | place | postcode | Y45 | country:gb | - When importing - Then location_postcode contains exactly - | postcode | country | rank_search | rank_address | - | E45 2CD | gb | 25 | 5 | - | E45 2 | gb | 23 | 5 | - | Y45 | gb | 21 | 5 | - - Scenario: Postcodes outside all countries are not added to the postcode table - Given the places - | osm | class | type | addr+postcode | addr+housenumber | addr+place | geometry | - | N34 | place | house | 01982 | 111 | Null Island | 0 0.00001 | - And the places - | osm | class | type | name | geometry | - | N1 | place | hamlet | Null Island | 0 0 | - When importing - Then location_postcode contains exactly - | country | postcode | geometry | - When sending search query "111, 01982 Null Island" - Then results contain - | osm | display_name | - | N34 | 111, Null Island, 01982 | diff --git a/test/bdd/db/import/rank_computation.feature b/test/bdd/db/import/rank_computation.feature deleted file mode 100644 index 0fce3e71..00000000 --- a/test/bdd/db/import/rank_computation.feature +++ /dev/null @@ -1,300 +0,0 @@ -@DB -Feature: Rank assignment - Tests for assignment of search and address ranks. - - Scenario: Ranks for place nodes are assigned according to their type - Given the named places - | osm | class | type | geometry | - | N1 | foo | bar | 0 0 | - | N11 | place | Continent | 0 0 | - | N12 | place | continent | 0 0 | - | N13 | place | sea | 0 0 | - | N14 | place | country | 0 0 | - | N15 | place | state | 0 0 | - | N16 | place | region | 0 0 | - | N17 | place | county | 0 0 | - | N18 | place | city | 0 0 | - | N19 | place | island | 0 0 | - | N36 | place | house | 0 0 | - And the named places - | osm | class | type | extra+capital | geometry | - | N101 | place | city | yes | 0 0 | - When importing - Then placex contains - | object | rank_search | rank_address | - | N1 | 30 | 30 | - | N11 | 22 | 0 | - | N12 | 2 | 0 | - | N13 | 2 | 0 | - | N14 | 4 | 0 | - | N15 | 8 | 0 | - | N16 | 18 | 0 | - | N17 | 12 | 12 | - | N18 | 16 | 16 | - | N19 | 17 | 0 | - | N101 | 15 | 16 | - | N36 | 30 | 30 | - - Scenario: Ranks for boundaries are assigned according to admin level - Given the named places - | osm | class | type | admin | geometry | - | R20 | boundary | administrative | 2 | (1 1, 2 2, 1 2, 1 1) | - | R21 | boundary | administrative | 32 | (3 3, 4 4, 3 4, 3 3) | - | R22 | boundary | administrative | 6 | (0 0, 1 0, 0 1, 0 0) | - | R23 | boundary | administrative | 10 | (0 0, 1 1, 1 0, 0 0) | - When importing - Then placex contains - | object | rank_search | rank_address | - | R20 | 4 | 4 | - | R21 | 25 | 0 | - | R22 | 12 | 12 | - | R23 | 20 | 20 | - - Scenario: Ranks for addressable boundaries with place assignment go with place address ranks if available - Given the named places - | osm | class | type | admin | extra+place | geometry | - | R20 | boundary | administrative | 3 | state | (1 1, 2 2, 1 2, 1 1) | - | R21 | boundary | administrative | 32 | suburb | (3 3, 4 4, 3 4, 3 3) | - | R22 | boundary | administrative | 6 | town | (0 0, 1 0, 0 1, 0 0) | - | R23 | boundary | administrative | 10 | village | (0 0, 1 1, 1 0, 0 0) | - When importing - Then placex contains - | object | rank_search | rank_address | - | R20 | 6 | 6 | - | R21 | 25 | 0 | - | R22 | 12 | 16 | - | R23 | 20 | 16 | - - Scenario: Place address ranks cannot overtake a parent address rank - Given the named places - | osm | class | type | admin | extra+place | geometry | - | R20 | boundary | administrative | 8 | town | (0 0, 0 2, 2 2, 2 0, 0 0) | - | R21 | boundary | administrative | 9 | municipality | (0 0, 0 1, 1 1, 1 0, 0 0) | - | R22 | boundary | administrative | 9 | suburb | (0 0, 0 1, 1 1, 1 0, 0 0) | - When importing - Then placex contains - | object | rank_search | rank_address | - | R20 | 16 | 16 | - | R21 | 18 | 18 | - | R22 | 18 | 20 | - Then place_addressline contains - | object | address | cached_rank_address | - | R21 | R20 | 16 | - | R22 | R20 | 16 | - - Scenario: Admin levels cannot overtake each other due to place address ranks - Given the named places - | osm | class | type | admin | extra+place | geometry | - | R20 | boundary | administrative | 6 | town | (0 0, 0 2, 2 2, 2 0, 0 0) | - | R21 | boundary | administrative | 8 | | (0 0, 0 1, 1 1, 1 0, 0 0) | - | R22 | boundary | administrative | 8 | suburb | (0 0, 0 1, 1 1, 1 0, 0 0) | - When importing - Then placex contains - | object | rank_search | rank_address | - | R20 | 12 | 16 | - | R21 | 16 | 18 | - | R22 | 16 | 20 | - Then place_addressline contains - | object | address | cached_rank_address | - | R21 | R20 | 16 | - | R22 | R20 | 16 | - - Scenario: Admin levels cannot overtake each other due to place address ranks even when slightly misaligned - Given the named places - | osm | class | type | admin | extra+place | geometry | - | R20 | boundary | administrative | 6 | town | (0 0, 0 2, 2 2, 2 0, 0 0) | - | R21 | boundary | administrative | 8 | | (0 0, -0.0001 1, 1 1, 1 0, 0 0) | - When importing - Then placex contains - | object | rank_search | rank_address | - | R20 | 12 | 16 | - | R21 | 16 | 18 | - Then place_addressline contains - | object | address | cached_rank_address | - | R21 | R20 | 16 | - - Scenario: Admin levels must not be larger than 25 - Given the named places - | osm | class | type | admin | extra+place | geometry | - | R20 | boundary | administrative | 6 | neighbourhood | (0 0, 0 2, 2 2, 2 0, 0 0) | - | R21 | boundary | administrative | 7 | | (0 0, 0 1, 1 1, 1 0, 0 0) | - | R22 | boundary | administrative | 8 | | (0 0, 0 0.5, 0.5 0.5, 0.5 0, 0 0) | - When importing - Then placex contains - | object | rank_search | rank_address | - | R20 | 12 | 22 | - | R21 | 14 | 24 | - | R22 | 16 | 25 | - - Scenario: admin levels contained in a place area must not overtake address ranks - Given the named places - | osm | class | type | admin | geometry | - | R10 | place | city | 15 | (0 0, 0 2, 2 0, 0 0) | - | R20 | boundary | administrative | 6 | (0 0, 0 1, 1 0, 0 0) | - When importing - Then placex contains - | object | rank_search | rank_address | - | R10 | 16 | 16 | - | R20 | 12 | 18 | - - Scenario: admin levels overlapping a place area are not demoted - Given the named places - | osm | class | type | admin | geometry | - | R10 | place | city | 15 | (0 0, 0 2, 2 0, 0 0) | - | R20 | boundary | administrative | 6 | (-1 0, 0 1, 1 0, -1 0) | - When importing - Then placex contains - | object | rank_search | rank_address | - | R10 | 16 | 16 | - | R20 | 12 | 12 | - - Scenario: admin levels with equal area as a place area are not demoted - Given the named places - | osm | class | type | admin | geometry | - | R10 | place | city | 15 | (0 0, 0 2, 2 0, 0 0) | - | R20 | boundary | administrative | 6 | (0 0, 0 2, 2 0, 0 0) | - When importing - Then placex contains - | object | rank_search | rank_address | - | R10 | 16 | 16 | - | R20 | 12 | 12 | - - - Scenario: adjacent admin_levels are considered the same object when they have the same wikidata - Given the named places - | osm | class | type | admin | extra+wikidata | geometry | - | N20 | place | square | 15 | Q123 | 0.1 0.1 | - | R23 | boundary | administrative | 10 | Q444 | (0 0, 0 1, 1 1, 1 0, 0 0) | - | R21 | boundary | administrative | 9 | Q444 | (0 0, 0 1, 1 1, 1 0, 0 0) | - | R22 | boundary | administrative | 8 | Q444 | (0 0, 0 1, 1 1, 1 0, 0 0) | - When importing - Then placex contains - | object | rank_search | rank_address | - | R23 | 20 | 0 | - | R21 | 18 | 0 | - | R22 | 16 | 16 | - Then place_addressline contains - | object | address | cached_rank_address | - | N20 | R22 | 16 | - Then place_addressline doesn't contain - | object | address | - | N20 | R21 | - | N20 | R23 | - - Scenario: adjacent admin_levels are considered different objects when they have different wikidata - Given the named places - | osm | class | type | admin | extra+wikidata | geometry | - | N20 | place | square | 15 | Q123 | 0.1 0.1 | - | R21 | boundary | administrative | 9 | Q4441 | (0 0, 0 1, 1 1, 1 0, 0 0) | - | R22 | boundary | administrative | 8 | Q444 | (0 0, 0 1, 1 1, 1 0, 0 0) | - When importing - Then placex contains - | object | rank_search | rank_address | - | R21 | 18 | 18 | - | R22 | 16 | 16 | - Then place_addressline contains - | object | address | cached_rank_address | - | N20 | R22 | 16 | - | N20 | R21 | 18 | - - Scenario: Mixes of admin boundaries and place areas I - Given the grid - | 1 | | 10 | | | 2 | - | | 9 | | | | | - | 20| | 21 | | | | - | 4 | | 11 | | | 3 | - And the places - | osm | class | type | admin | name | geometry | - | R1 | boundary | administrative | 5 | Greater London | (1,2,3,4,1) | - | R2 | boundary | administrative | 8 | Kensington | (1,10,11,4,1) | - And the places - | osm | class | type | name | geometry | - | R10 | place | city | London | (1,2,3,4,1) | - | N9 | place | town | Fulham | 9 | - | W1 | highway | residential | Lots Grove | 20,21 | - When importing - Then placex contains - | object | rank_search | rank_address | - | R1 | 10 | 10 | - | R10 | 16 | 16 | - | R2 | 16 | 18 | - | N9 | 18 | 18 | - And place_addressline contains - | object | address | isaddress | cached_rank_address | - | W1 | R1 | True | 10 | - | W1 | R10 | True | 16 | - | W1 | R2 | True | 18 | - | W1 | N9 | False | 18 | - - - Scenario: Mixes of admin boundaries and place areas II - Given the grid - | 1 | | 10 | | 5 | 2 | - | | 9 | | | | | - | 20| | 21 | | | | - | 4 | | 11 | | 6 | 3 | - And the places - | osm | class | type | admin | name | geometry | - | R1 | boundary | administrative | 5 | Greater London | (1,2,3,4,1) | - | R2 | boundary | administrative | 8 | London | (1,5,6,4,1) | - And the places - | osm | class | type | name | geometry | - | R10 | place | city | Westminster | (1,10,11,4,1) | - | N9 | place | town | Fulham | 9 | - | W1 | highway | residential | Lots Grove | 20,21 | - When importing - Then placex contains - | object | rank_search | rank_address | - | R1 | 10 | 10 | - | R2 | 16 | 16 | - | R10 | 16 | 18 | - | N9 | 18 | 18 | - And place_addressline contains - | object | address | isaddress | cached_rank_address | - | W1 | R1 | True | 10 | - | W1 | R10 | True | 18 | - | W1 | R2 | True | 16 | - | W1 | N9 | False | 18 | - - - Scenario: POI nodes with place tags - Given the places - | osm | class | type | name | extratags | - | N23 | amenity | playground | AB | "place": "city" | - | N23 | place | city | AB | "amenity": "playground" | - When importing - Then placex contains exactly - | object | rank_search | rank_address | - | N23:amenity | 30 | 30 | - | N23:place | 16 | 16 | - - Scenario: Address rank 25 is only used for addr:place - Given the grid - | 10 | 33 | 34 | 11 | - Given the places - | osm | class | type | name | - | N10 | place | village | vil | - | N11 | place | farm | farm | - And the places - | osm | class | type | name | geometry | - | W1 | highway | residential | RD | 33,11 | - And the places - | osm | class | type | name | addr+farm | geometry | - | W2 | highway | residential | RD2 | farm | 34,11 | - And the places - | osm | class | type | housenr | - | N33 | place | house | 23 | - And the places - | osm | class | type | housenr | addr+place | - | N34 | place | house | 23 | farm | - When importing - Then placex contains - | object | parent_place_id | - | N11 | N10 | - | N33 | W1 | - | N34 | N11 | - And place_addressline contains - | object | address | - | W1 | N10 | - | W2 | N10 | - | W2 | N11 | diff --git a/test/bdd/db/import/search_name.feature b/test/bdd/db/import/search_name.feature deleted file mode 100644 index cd581c46..00000000 --- a/test/bdd/db/import/search_name.feature +++ /dev/null @@ -1,428 +0,0 @@ -@DB -Feature: Creation of search terms - Tests that search_name table is filled correctly - - Scenario: Semicolon-separated names appear as separate full names - Given the places - | osm | class | type | name+alt_name | - | N1 | place | city | New York; Big Apple | - When importing - Then search_name contains - | object | name_vector | - | N1 | #New York, #Big Apple | - - Scenario: Comma-separated names appear as a single full name - Given the places - | osm | class | type | name+alt_name | - | N1 | place | city | New York, Big Apple | - When importing - Then search_name contains - | object | name_vector | - | N1 | #New York Big Apple | - - Scenario: Name parts before brackets appear as full names - Given the places - | osm | class | type | name+name | - | N1 | place | city | Halle (Saale) | - When importing - Then search_name contains - | object | name_vector | - | N1 | #Halle Saale, #Halle | - - Scenario: Unnamed POIs have no search entry - Given the grid - | | 1 | | | - | 10 | | | 11 | - And the places - | osm | class | type | - | N1 | place | house | - And the named places - | osm | class | type | geometry | - | W1 | highway | residential | 10,11 | - When importing - Then search_name has no entry for N1 - - Scenario: Unnamed POI has a search entry when it has unknown addr: tags - Given the grid - | | 1 | | | - | 10 | | | 11 | - And the places - | osm | class | type | housenr | addr+city | - | N1 | place | house | 23 | Walltown | - And the places - | osm | class | type | name+name | geometry | - | W1 | highway | residential | Rose Street | 10,11 | - When importing - Then search_name contains - | object | nameaddress_vector | - | N1 | #Rose Street, Walltown | - When sending search query "23 Rose Street, Walltown" - Then results contain - | osm | display_name | - | N1 | 23, Rose Street | - When sending search query "Walltown, Rose Street 23" - Then results contain - | osm | display_name | - | N1 | 23, Rose Street | - When sending search query "Rose Street 23, Walltown" - Then results contain - | osm | display_name | - | N1 | 23, Rose Street | - - Scenario: Searching for unknown addr: tags also works for multiple words - Given the grid - | | 1 | | | - | 10 | | | 11 | - And the places - | osm | class | type | housenr | addr+city | - | N1 | place | house | 23 | Little Big Town | - And the places - | osm | class | type | name+name | geometry | - | W1 | highway | residential | Rose Street | 10,11 | - When importing - Then search_name contains - | object | nameaddress_vector | - | N1 | #Rose Street, rose, Little, Big, Town | - When sending search query "23 Rose Street, Little Big Town" - Then results contain - | osm | display_name | - | N1 | 23, Rose Street | - When sending search query "Rose Street 23, Little Big Town" - Then results contain - | osm | display_name | - | N1 | 23, Rose Street | - When sending search query "Little big Town, Rose Street 23" - Then results contain - | osm | display_name | - | N1 | 23, Rose Street | - - Scenario: Unnamed POI has no search entry when it has known addr: tags - Given the grid - | | 1 | | | - | 10 | | | 11 | - And the places - | osm | class | type | housenr | addr+city | - | N1 | place | house | 23 | Walltown | - And the places - | osm | class | type | name+name | addr+city | geometry | - | W1 | highway | residential | Rose Street | Walltown | 10,11 | - When importing - Then search_name has no entry for N1 - When sending search query "23 Rose Street, Walltown" - Then results contain - | osm | display_name | - | N1 | 23, Rose Street | - - Scenario: Unnamed POI must have a house number to get a search entry - Given the grid - | | 1 | | | - | 10 | | | 11 | - And the places - | osm | class | type | addr+city | - | N1 | place | house | Walltown | - And the places - | osm | class | type | name+name | geometry | - | W1 | highway | residential | Rose Street | 10,11 | - When importing - Then search_name has no entry for N1 - - Scenario: Unnamed POIs inherit parent name when unknown addr:place is present - Given the grid - | 100 | | | | | 101 | - | | | 1 | | | | - | 103 | 10 | | | 11 | 102 | - And the places - | osm | class | type | housenr | addr+place | - | N1 | place | house | 23 | Walltown | - And the places - | osm | class | type | name+name | geometry | - | W1 | highway | residential | Rose Street | 10,11 | - | R1 | place | city | Strange Town | (100,101,102,103,100) | - When importing - Then placex contains - | object | parent_place_id | - | N1 | R1 | - When sending search query "23 Rose Street" - Then exactly 1 results are returned - And results contain - | osm | display_name | - | W1 | Rose Street, Strange Town | - When sending search query "23 Walltown, Strange Town" - Then results contain - | osm | display_name | - | N1 | 23, Walltown, Strange Town | - When sending search query "Walltown 23, Strange Town" - Then results contain - | osm | display_name | - | N1 | 23, Walltown, Strange Town | - When sending search query "Strange Town, Walltown 23" - Then results contain - | osm | display_name | - | N1 | 23, Walltown, Strange Town | - - Scenario: Named POIs can be searched by housenumber when unknown addr:place is present - Given the grid - | 100 | | | | | 101 | - | | | 1 | | | | - | 103 | 10 | | | 11 | 102 | - And the places - | osm | class | type | name | housenr | addr+place | - | N1 | place | house | Blue house | 23 | Walltown | - And the places - | osm | class | type | name+name | geometry | - | W1 | highway | residential | Rose Street | 10,11 | - | R1 | place | city | Strange Town | (100,101,102,103,100) | - When importing - When sending search query "23 Walltown, Strange Town" - Then results contain - | osm | display_name | - | N1 | Blue house, 23, Walltown, Strange Town | - When sending search query "Walltown 23, Strange Town" - Then results contain - | osm | display_name | - | N1 | Blue house, 23, Walltown, Strange Town | - When sending search query "Strange Town, Walltown 23" - Then results contain - | osm | display_name | - | N1 | Blue house, 23, Walltown, Strange Town | - When sending search query "Strange Town, Walltown 23, Blue house" - Then results contain - | osm | display_name | - | N1 | Blue house, 23, Walltown, Strange Town | - When sending search query "Strange Town, Walltown, Blue house" - Then results contain - | osm | display_name | - | N1 | Blue house, 23, Walltown, Strange Town | - - Scenario: Named POIs can be found when unknown multi-word addr:place is present - Given the grid - | 100 | | | | | 101 | - | | | 1 | | | | - | 103 | 10 | | | 11 | 102 | - And the places - | osm | class | type | name | housenr | addr+place | - | N1 | place | house | Blue house | 23 | Moon sun | - And the places - | osm | class | type | name+name | geometry | - | W1 | highway | residential | Rose Street | 10,11 | - | R1 | place | city | Strange Town | (100,101,102,103,100) | - When importing - When sending search query "23 Moon Sun, Strange Town" - Then results contain - | osm | display_name | - | N1 | Blue house, 23, Moon sun, Strange Town | - When sending search query "Blue house, Moon Sun, Strange Town" - Then results contain - | osm | display_name | - | N1 | Blue house, 23, Moon sun, Strange Town | - - Scenario: Unnamed POIs doesn't inherit parent name when addr:place is present only in parent address - Given the grid - | 100 | | | | | 101 | - | | | 1 | | | | - | 103 | 10 | | | 11 | 102 | - And the places - | osm | class | type | housenr | addr+place | - | N1 | place | house | 23 | Walltown | - And the places - | osm | class | type | name+name | addr+city | geometry | - | W1 | highway | residential | Rose Street | Walltown | 10,11 | - | R1 | place | suburb | Strange Town | Walltown | (100,101,102,103,100) | - When importing - When sending search query "23 Rose Street, Walltown" - Then exactly 1 result is returned - And results contain - | osm | display_name | - | W1 | Rose Street, Strange Town | - When sending search query "23 Walltown" - Then exactly 1 result is returned - And results contain - | osm | display_name | - | N1 | 23, Walltown, Strange Town | - - Scenario: Unnamed POIs does inherit parent name when unknown addr:place and addr:street is present - Given the grid - | | 1 | | | - | 10 | | | 11 | - And the places - | osm | class | type | housenr | addr+place | addr+street | - | N1 | place | house | 23 | Walltown | Lily Street | - And the places - | osm | class | type | name+name | geometry | - | W1 | highway | residential | Rose Street | 10,11 | - When importing - Then search_name has no entry for N1 - When sending search query "23 Rose Street" - Then results contain - | osm | display_name | - | N1 | 23, Rose Street | - When sending search query "23 Lily Street" - Then exactly 0 results are returned - - Scenario: An unknown addr:street is ignored - Given the grid - | | 1 | | | - | 10 | | | 11 | - And the places - | osm | class | type | housenr | addr+street | - | N1 | place | house | 23 | Lily Street | - And the places - | osm | class | type | name+name | geometry | - | W1 | highway | residential | Rose Street | 10,11 | - When importing - Then search_name has no entry for N1 - When sending search query "23 Rose Street" - Then results contain - | osm | display_name | - | N1 | 23, Rose Street | - When sending search query "23 Lily Street" - Then exactly 0 results are returned - - Scenario: Named POIs get unknown address tags added in the search_name table - Given the grid - | | 1 | | | - | 10 | | | 11 | - And the places - | osm | class | type | name+name | housenr | addr+city | - | N1 | place | house | Green Moss | 26 | Walltown | - And the places - | osm | class | type | name+name | geometry | - | W1 | highway | residential | Rose Street | 10,11 | - When importing - Then search_name contains - | object | name_vector | nameaddress_vector | - | N1 | #Green Moss | #Rose Street, Walltown | - When sending search query "Green Moss, Rose Street, Walltown" - Then results contain - | osm | display_name | - | N1 | Green Moss, 26, Rose Street | - When sending search query "Green Moss, 26, Rose Street, Walltown" - Then results contain - | osm | display_name | - | N1 | Green Moss, 26, Rose Street | - When sending search query "26, Rose Street, Walltown" - Then results contain - | osm | display_name | - | N1 | Green Moss, 26, Rose Street | - When sending search query "Rose Street 26, Walltown" - Then results contain - | osm | display_name | - | N1 | Green Moss, 26, Rose Street | - When sending search query "Walltown, Rose Street 26" - Then results contain - | osm | display_name | - | N1 | Green Moss, 26, Rose Street | - - Scenario: Named POI doesn't inherit parent name when addr:place is present only in parent address - Given the grid - | 100 | | | | | 101 | - | | | 1 | | | | - | 103 | 10 | | | 11 | 102 | - And the places - | osm | class | type | name+name | addr+place | - | N1 | place | house | Green Moss | Walltown | - And the places - | osm | class | type | name+name | geometry | - | W1 | highway | residential | Rose Street | 10,11 | - | R1 | place | suburb | Strange Town | (100,101,102,103,100) | - When importing - When sending search query "Green Moss, Rose Street, Walltown" - Then exactly 0 result is returned - When sending search query "Green Moss, Walltown" - Then results contain - | osm | display_name | - | N1 | Green Moss, Walltown, Strange Town | - - Scenario: Named POIs inherit address from parent - Given the grid - | | 1 | | | - | 10 | | | 11 | - And the places - | osm | class | type | name | geometry | - | N1 | place | house | foo | 1 | - | W1 | highway | residential | the road | 10,11 | - When importing - Then search_name contains - | object | name_vector | nameaddress_vector | - | N1 | foo | #the road | - - Scenario: Some addr: tags are added to address - Given the grid - | | 2 | 3 | | - | 10 | | | 11 | - And the places - | osm | class | type | name | - | N2 | place | city | bonn | - | N3 | place | suburb | smalltown| - And the named places - | osm | class | type | addr+city | addr+municipality | addr+suburb | geometry | - | W1 | highway | service | bonn | New York | Smalltown | 10,11 | - When importing - Then search_name contains - | object | nameaddress_vector | - | W1 | bonn, new, york, smalltown | - - Scenario: A known addr:* tag is added even if the name is unknown - Given the grid - | 10 | | | | 11 | - And the places - | osm | class | type | name | addr+city | geometry | - | W1 | highway | residential | Road | Nandu | 10,11 | - When importing - Then search_name contains - | object | nameaddress_vector | - | W1 | nandu | - - Scenario: addr:postcode is not added to the address terms - Given the grid with origin DE - | | 1 | | | - | 10 | | | 11 | - And the places - | osm | class | type | name+ref | - | N1 | place | state | 12345 | - And the named places - | osm | class | type | addr+postcode | geometry | - | W1 | highway | residential | 12345 | 10,11 | - When importing - Then search_name contains not - | object | nameaddress_vector | - | W1 | 12345 | - - Scenario: a linked place does not show up in search name - Given the 0.01 grid - | 10 | | 11 | - | | 2 | | - | 13 | | 12 | - Given the named places - | osm | class | type | admin | geometry | - | R13 | boundary | administrative | 9 | (10,11,12,13,10) | - And the named places - | osm | class | type | - | N2 | place | city | - And the relations - | id | members | tags+type | - | 13 | N2:label | boundary | - When importing - Then placex contains - | object | linked_place_id | - | N2 | R13 | - And search_name has no entry for N2 - - Scenario: a linked waterway does not show up in search name - Given the grid - | 1 | | 2 | | 3 | - And the places - | osm | class | type | name | geometry | - | W1 | waterway | river | Rhein | 1,2 | - | W2 | waterway | river | Rhein | 2,3 | - | R13 | waterway | river | Rhein | 1,2,3 | - And the relations - | id | members | tags+type | - | 13 | W1,W2:main_stream | waterway | - When importing - Then placex contains - | object | linked_place_id | - | W1 | R13 | - | W2 | R13 | - And search_name has no entry for W1 - And search_name has no entry for W2 diff --git a/test/bdd/db/query/housenumbers.feature b/test/bdd/db/query/housenumbers.feature deleted file mode 100644 index 16d9fd5a..00000000 --- a/test/bdd/db/query/housenumbers.feature +++ /dev/null @@ -1,321 +0,0 @@ -@DB -Feature: Searching of house numbers - Test for specialised treeatment of housenumbers - - Background: - Given the grid - | 1 | | 2 | | 3 | - | | 9 | | | | - | | | | | 4 | - - - Scenario: A simple ascii digit housenumber is found - Given the places - | osm | class | type | housenr | geometry | - | N1 | building | yes | 45 | 9 | - And the places - | osm | class | type | name | geometry | - | W10 | highway | path | North Road | 1,2,3 | - When importing - And sending search query "45, North Road" - Then results contain - | osm | - | N1 | - When sending search query "North Road 45" - Then results contain - | osm | - | N1 | - - - Scenario Outline: Numeral housenumbers in any script are found - Given the places - | osm | class | type | housenr | geometry | - | N1 | building | yes | | 9 | - And the places - | osm | class | type | name | geometry | - | W10 | highway | path | North Road | 1,2,3 | - When importing - And sending search query "45, North Road" - Then results contain - | osm | - | N1 | - When sending search query "North Road ④⑤" - Then results contain - | osm | - | N1 | - When sending search query "North Road 𑁪𑁫" - Then results contain - | osm | - | N1 | - - Examples: - | number | - | 45 | - | ④⑤ | - | 𑁪𑁫 | - - - Scenario Outline: Each housenumber in a list is found - Given the places - | osm | class | type | housenr | geometry | - | N1 | building | yes | | 9 | - And the places - | osm | class | type | name | geometry | - | W10 | highway | path | Multistr | 1,2,3 | - When importing - When sending search query "2 Multistr" - Then results contain - | osm | - | N1 | - When sending search query "4 Multistr" - Then results contain - | osm | - | N1 | - When sending search query "12 Multistr" - Then results contain - | osm | - | N1 | - - Examples: - | hnrs | - | 2;4;12 | - | 2,4,12 | - | 2, 4, 12 | - - - Scenario Outline: Housenumber - letter combinations are found - Given the places - | osm | class | type | housenr | geometry | - | N1 | building | yes | | 9 | - And the places - | osm | class | type | name | geometry | - | W10 | highway | path | Multistr | 1,2,3 | - When importing - When sending search query "2A Multistr" - Then results contain - | osm | - | N1 | - When sending search query "2 a Multistr" - Then results contain - | osm | - | N1 | - When sending search query "2-A Multistr" - Then results contain - | osm | - | N1 | - When sending search query "Multistr 2 A" - Then results contain - | osm | - | N1 | - - Examples: - | hnr | - | 2a | - | 2 A | - | 2-a | - | 2/A | - - - Scenario Outline: Number - Number combinations as a housenumber are found - Given the places - | osm | class | type | housenr | geometry | - | N1 | building | yes | | 9 | - And the places - | osm | class | type | name | geometry | - | W10 | highway | path | Chester St | 1,2,3 | - When importing - When sending search query "34-10 Chester St" - Then results contain - | osm | - | N1 | - When sending search query "34/10 Chester St" - Then results contain - | osm | - | N1 | - When sending search query "34 10 Chester St" - Then results contain - | osm | - | N1 | - When sending search query "3410 Chester St" - Then results contain - | osm | - | W10 | - - Examples: - | hnr | - | 34-10 | - | 34 10 | - | 34/10 | - - - Scenario Outline: a bis housenumber is found - Given the places - | osm | class | type | housenr | geometry | - | N1 | building | yes | | 9 | - And the places - | osm | class | type | name | geometry | - | W10 | highway | path | Rue Paris | 1,2,3 | - When importing - When sending search query "Rue Paris 45bis" - Then results contain - | osm | - | N1 | - When sending search query "Rue Paris 45 BIS" - Then results contain - | osm | - | N1 | - When sending search query "Rue Paris 45BIS" - Then results contain - | osm | - | N1 | - When sending search query "Rue Paris 45 bis" - Then results contain - | osm | - | N1 | - - Examples: - | hnr | - | 45bis | - | 45BIS | - | 45 BIS | - | 45 bis | - - - Scenario Outline: a ter housenumber is found - Given the places - | osm | class | type | housenr | geometry | - | N1 | building | yes | | 9 | - And the places - | osm | class | type | name | geometry | - | W10 | highway | path | Rue du Berger | 1,2,3 | - When importing - When sending search query "Rue du Berger 45ter" - Then results contain - | osm | - | N1 | - When sending search query "Rue du Berger 45 TER" - Then results contain - | osm | - | N1 | - When sending search query "Rue du Berger 45TER" - Then results contain - | osm | - | N1 | - When sending search query "Rue du Berger 45 ter" - Then results contain - | osm | - | N1 | - - Examples: - | hnr | - | 45ter | - | 45TER | - | 45 ter | - | 45 TER | - - - Scenario Outline: a number - letter - number combination housenumber is found - Given the places - | osm | class | type | housenr | geometry | - | N1 | building | yes | | 9 | - And the places - | osm | class | type | name | geometry | - | W10 | highway | path | Herengracht | 1,2,3 | - When importing - When sending search query "501-H 1 Herengracht" - Then results contain - | osm | - | N1 | - When sending search query "501H-1 Herengracht" - Then results contain - | osm | - | N1 | - When sending search query "501H1 Herengracht" - Then results contain - | osm | - | N1 | - When sending search query "501-H1 Herengracht" - Then results contain - | osm | - | N1 | - - Examples: - | hnr | - | 501 H1 | - | 501H 1 | - | 501/H/1 | - | 501h1 | - - - Scenario Outline: Russian housenumbers are found - Given the places - | osm | class | type | housenr | geometry | - | N1 | building | yes | | 9 | - And the places - | osm | class | type | name | geometry | - | W10 | highway | path | Голубинская улица | 1,2,3 | - When importing - When sending search query "Голубинская улица 55к3" - Then results contain - | osm | - | N1 | - When sending search query "Голубинская улица 55 k3" - Then results contain - | osm | - | N1 | - When sending search query "Голубинская улица 55 к-3" - Then results contain - | osm | - | N1 | - - Examples: - | hnr | - | 55к3 | - | 55 к3 | - - - Scenario: A name mapped as a housenumber is found - Given the places - | osm | class | type | housenr | geometry | - | N1 | building | yes | Warring | 9 | - And the places - | osm | class | type | name | geometry | - | W10 | highway | path | Chester St | 1,2,3 | - When importing - When sending search query "Chester St Warring" - Then results contain - | osm | - | N1 | - - - Scenario: Interpolations are found according to their type - Given the grid - | 10 | | 11 | - | 100 | | 101 | - | 20 | | 21 | - And the places - | osm | class | type | name | geometry | - | W100 | highway | residential | Ringstr | 100, 101 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W10 | place | houses | even | 10, 11 | - | W20 | place | houses | odd | 20, 21 | - And the places - | osm | class | type | housenr | geometry | - | N10 | place | house | 10 | 10 | - | N11 | place | house | 20 | 11 | - | N20 | place | house | 11 | 20 | - | N21 | place | house | 21 | 21 | - And the ways - | id | nodes | - | 10 | 10, 11 | - | 20 | 20, 21 | - When importing - When sending search query "Ringstr 12" - Then results contain - | osm | - | W10 | - When sending search query "Ringstr 13" - Then results contain - | osm | - | W20 | diff --git a/test/bdd/db/query/interpolation.feature b/test/bdd/db/query/interpolation.feature deleted file mode 100644 index 600de718..00000000 --- a/test/bdd/db/query/interpolation.feature +++ /dev/null @@ -1,58 +0,0 @@ -@DB -Feature: Query of address interpolations - Tests that interpolated addresses can be queried correctly - - Background: - Given the grid - | 1 | | 2 | | 3 | - | 10 | | 12 | | 13 | - | 7 | | 8 | | 9 | - - Scenario: Find interpolations with single number - Given the places - | osm | class | type | name | geometry | - | W10 | highway | primary | Nickway | 10,12,13 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | odd | 1,3 | - And the places - | osm | class | type | housenr | geometry | - | N1 | place | house | 1 | 1 | - | N3 | place | house | 5 | 3 | - And the ways - | id | nodes | - | 1 | 1,3 | - When importing - When sending v1/reverse N2 - Then results contain - | ID | display_name | - | 0 | 3, Nickway | - When sending search query "Nickway 3" - Then results contain - | osm | display_name | - | W1 | 3, Nickway | - - - Scenario: Find interpolations with multiple numbers - Given the places - | osm | class | type | name | geometry | - | W10 | highway | primary | Nickway | 10,12,13 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 1,3 | - And the places - | osm | class | type | housenr | geometry | - | N1 | place | house | 2 | 1 | - | N3 | place | house | 18 | 3 | - And the ways - | id | nodes | - | 1 | 1,3 | - When importing - When sending v1/reverse N2 - Then results contain - | ID | display_name | centroid | - | 0 | 10, Nickway | 2 | - When sending search query "Nickway 10" - Then results contain - | osm | display_name | centroid | - | W1 | 10, Nickway | 2 | diff --git a/test/bdd/db/query/japanese.feature b/test/bdd/db/query/japanese.feature deleted file mode 100644 index f21e0f5c..00000000 --- a/test/bdd/db/query/japanese.feature +++ /dev/null @@ -1,29 +0,0 @@ -@DB -Feature: Searches in Japan - Test specifically for searches of Japanese addresses and in Japanese language. - Scenario: A block house-number is parented to the neighbourhood - Given the grid with origin JP - | 1 | | | | 2 | - | | 3 | | | | - | | | 9 | | | - | | | | 6 | | - And the places - | osm | class | type | name | geometry | - | W1 | highway | residential | 雉子橋通り | 1,2 | - And the places - | osm | class | type | housenr | addr+block_number | addr+neighbourhood | geometry | - | N3 | amenity | restaurant | 2 | 6 | 2丁目 | 3 | - And the places - | osm | class | type | name | geometry | - | N9 | place | neighbourhood | 2丁目 | 9 | - And the places - | osm | class | type | name | geometry | - | N6 | place | quarter | 加瀬 | 6 | - When importing - Then placex contains - | object | parent_place_id | - | N3 | N9 | - When sending search query "2丁目 6-2" - Then results contain - | osm | - | N3 | diff --git a/test/bdd/db/query/linking.feature b/test/bdd/db/query/linking.feature deleted file mode 100644 index 351f8871..00000000 --- a/test/bdd/db/query/linking.feature +++ /dev/null @@ -1,64 +0,0 @@ -@DB -Feature: Searching linked places - Tests that information from linked places can be searched correctly - - Scenario: Additional names from linked places are searchable - Given the 0.1 grid - | 10 | | 11 | - | | 2 | | - | 13 | | 12 | - Given the places - | osm | class | type | admin | name | geometry | - | R13 | boundary | administrative | 6 | Garbo | (10,11,12,13,10) | - Given the places - | osm | class | type | admin | name+name:it | - | N2 | place | hamlet | 15 | Vario | - And the relations - | id | members | tags+type | - | 13 | N2:label | boundary | - When importing - Then placex contains - | object | linked_place_id | - | N2 | R13 | - When sending search query "Vario" - | namedetails | - | 1 | - Then results contain - | osm | display_name | namedetails | - | R13 | Garbo | "name": "Garbo", "name:it": "Vario" | - When sending search query "Vario" - | accept-language | - | it | - Then results contain - | osm | display_name | - | R13 | Vario | - - - Scenario: Differing names from linked places are searchable - Given the 0.1 grid - | 10 | | 11 | - | | 2 | | - | 13 | | 12 | - Given the places - | osm | class | type | admin | name | geometry | - | R13 | boundary | administrative | 6 | Garbo | (10,11,12,13,10) | - Given the places - | osm | class | type | admin | name | - | N2 | place | hamlet | 15 | Vario | - And the relations - | id | members | tags+type | - | 13 | N2:label | boundary | - When importing - Then placex contains - | object | linked_place_id | - | N2 | R13 | - When sending search query "Vario" - | namedetails | - | 1 | - Then results contain - | osm | display_name | namedetails | - | R13 | Garbo | "name": "Garbo", "_place_name": "Vario" | - When sending search query "Garbo" - Then results contain - | osm | display_name | - | R13 | Garbo | diff --git a/test/bdd/db/query/normalization.feature b/test/bdd/db/query/normalization.feature deleted file mode 100644 index 47906133..00000000 --- a/test/bdd/db/query/normalization.feature +++ /dev/null @@ -1,226 +0,0 @@ -@DB -Feature: Import and search of names - Tests all naming related issues: normalisation, - abbreviations, internationalisation, etc. - - Scenario: non-latin scripts can be found - Given the places - | osm | class | type | name | - | N1 | place | locality | Речицкий район | - | N2 | place | locality | Refugio de montaña | - | N3 | place | locality | 高槻市| - | N4 | place | locality | الدوحة | - When importing - When sending search query "Речицкий район" - Then results contain - | ID | osm | - | 0 | N1 | - When sending search query "Refugio de montaña" - Then results contain - | ID | osm | - | 0 | N2 | - When sending search query "高槻市" - Then results contain - | ID | osm | - | 0 | N3 | - When sending search query "الدوحة" - Then results contain - | ID | osm | - | 0 | N4 | - - Scenario: Case-insensitivity of search - Given the places - | osm | class | type | name | - | N1 | place | locality | FooBar | - When importing - Then placex contains - | object | class | type | name+name | - | N1 | place | locality | FooBar | - When sending search query "FooBar" - Then results contain - | ID | osm | - | 0 | N1 | - When sending search query "foobar" - Then results contain - | ID | osm | - | 0 | N1 | - When sending search query "fOObar" - Then results contain - | ID | osm | - | 0 | N1 | - When sending search query "FOOBAR" - Then results contain - | ID | osm | - | 0 | N1 | - - Scenario: Multiple spaces in name - Given the places - | osm | class | type | name | - | N1 | place | locality | one two three | - When importing - When sending search query "one two three" - Then results contain - | ID | osm | - | 0 | N1 | - When sending search query "one two three" - Then results contain - | ID | osm | - | 0 | N1 | - When sending search query "one two three" - Then results contain - | ID | osm | - | 0 | N1 | - When sending search query " one two three" - Then results contain - | ID | osm | - | 0 | N1 | - - Scenario: Special characters in name - Given the places - | osm | class | type | name+name:de | - | N1 | place | locality | Jim-Knopf-Straße | - | N2 | place | locality | Smith/Weston | - | N3 | place | locality | space mountain | - | N4 | place | locality | space | - | N5 | place | locality | mountain | - When importing - When sending search query "Jim-Knopf-Str" - Then results contain - | ID | osm | - | 0 | N1 | - When sending search query "Jim Knopf-Str" - Then results contain - | ID | osm | - | 0 | N1 | - When sending search query "Jim Knopf Str" - Then results contain - | ID | osm | - | 0 | N1 | - When sending search query "Jim/Knopf-Str" - Then results contain - | ID | osm | - | 0 | N1 | - When sending search query "Jim-Knopfstr" - Then results contain - | ID | osm | - | 0 | N1 | - When sending search query "Smith/Weston" - Then results contain - | ID | osm | - | 0 | N2 | - When sending search query "Smith Weston" - Then results contain - | ID | osm | - | 0 | N2 | - When sending search query "Smith-Weston" - Then results contain - | ID | osm | - | 0 | N2 | - When sending search query "space mountain" - Then results contain - | ID | osm | - | 0 | N3 | - When sending search query "space-mountain" - Then results contain - | ID | osm | - | 0 | N3 | - When sending search query "space/mountain" - Then results contain - | ID | osm | - | 0 | N3 | - When sending search query "space\mountain" - Then results contain - | ID | osm | - | 0 | N3 | - When sending search query "space(mountain)" - Then results contain - | ID | osm | - | 0 | N3 | - - Scenario: Landuse with name are found - Given the grid - | 1 | 2 | - | 3 | | - Given the places - | osm | class | type | name | geometry | - | R1 | natural | meadow | landuse1 | (1,2,3,1) | - | R2 | landuse | industrial | landuse2 | (2,3,1,2) | - When importing - When sending search query "landuse1" - Then results contain - | ID | osm | - | 0 | R1 | - When sending search query "landuse2" - Then results contain - | ID | osm | - | 0 | R2 | - - Scenario: Postcode boundaries without ref - Given the grid with origin FR - | | 2 | | - | 1 | | 3 | - Given the places - | osm | class | type | postcode | geometry | - | R1 | boundary | postal_code | 123-45 | (1,2,3,1) | - When importing - When sending search query "123-45" - Then results contain - | ID | osm | - | 0 | R1 | - - Scenario Outline: Housenumbers with special characters are found - Given the grid - | 1 | | | | 2 | - | | | 9 | | | - And the places - | osm | class | type | name | geometry | - | W1 | highway | primary | Main St | 1,2 | - And the places - | osm | class | type | housenr | geometry | - | N1 | building | yes | | 9 | - When importing - And sending search query "Main St " - Then results contain - | osm | display_name | - | N1 | , Main St | - - Examples: - | nr | - | 1 | - | 3456 | - | 1 a | - | 56b | - | 1 A | - | 2號 | - | 1Б | - | 1 к1 | - | 23-123 | - - Scenario Outline: Housenumbers in lists are found - Given the grid - | 1 | | | | 2 | - | | | 9 | | | - And the places - | osm | class | type | name | geometry | - | W1 | highway | primary | Main St | 1,2 | - And the places - | osm | class | type | housenr | geometry | - | N1 | building | yes | | 9 | - When importing - And sending search query "Main St " - Then results contain - | ID | osm | display_name | - | 0 | N1 | , Main St | - - Examples: - | nr-list | nr | - | 1,2,3 | 1 | - | 1,2,3 | 2 | - | 1, 2, 3 | 3 | - | 45 ;67;3 | 45 | - | 45 ;67;3 | 67 | - | 1a;1k | 1a | - | 1a;1k | 1k | - | 34/678 | 34 | - | 34/678 | 678 | - | 34/678 | 34/678 | diff --git a/test/bdd/db/query/postcodes.feature b/test/bdd/db/query/postcodes.feature deleted file mode 100644 index e8a2ccc2..00000000 --- a/test/bdd/db/query/postcodes.feature +++ /dev/null @@ -1,110 +0,0 @@ -@DB -Feature: Querying fo postcode variants - - Scenario: Postcodes in Singapore (6-digit postcode) - Given the grid with origin SG - | 10 | | | | 11 | - And the places - | osm | class | type | name | addr+postcode | geometry | - | W1 | highway | path | Lorang | 399174 | 10,11 | - When importing - When sending search query "399174" - Then results contain - | ID | type | display_name | - | 0 | postcode | 399174, Singapore | - - - Scenario Outline: Postcodes in the Netherlands (mixed postcode with spaces) - Given the grid with origin NL - | 10 | | | | 11 | - And the places - | osm | class | type | name | addr+postcode | geometry | - | W1 | highway | path | De Weide | 3993 DX | 10,11 | - When importing - When sending search query "3993 DX" - Then results contain - | ID | type | display_name | - | 0 | postcode | 3993 DX, Nederland | - When sending search query "3993dx" - Then results contain - | ID | type | display_name | - | 0 | postcode | 3993 DX, Nederland | - - Examples: - | postcode | - | 3993 DX | - | 3993DX | - | 3993 dx | - - - Scenario: Postcodes in Singapore (6-digit postcode) - Given the grid with origin SG - | 10 | | | | 11 | - And the places - | osm | class | type | name | addr+postcode | geometry | - | W1 | highway | path | Lorang | 399174 | 10,11 | - When importing - When sending search query "399174" - Then results contain - | ID | type | display_name | - | 0 | postcode | 399174, Singapore | - - - Scenario Outline: Postcodes in Andorra (with country code) - Given the grid with origin AD - | 10 | | | | 11 | - And the places - | osm | class | type | name | addr+postcode | geometry | - | W1 | highway | path | Lorang | | 10,11 | - When importing - When sending search query "675" - Then results contain - | ID | type | display_name | - | 0 | postcode | AD675, Andorra | - When sending search query "AD675" - Then results contain - | ID | type | display_name | - | 0 | postcode | AD675, Andorra | - - Examples: - | postcode | - | 675 | - | AD 675 | - | AD675 | - - - Scenario: Different postcodes with the same normalization can both be found - Given the places - | osm | class | type | addr+postcode | addr+housenumber | geometry | - | N34 | place | house | EH4 7EA | 111 | country:gb | - | N35 | place | house | E4 7EA | 111 | country:gb | - When importing - Then location_postcode contains exactly - | country | postcode | geometry | - | gb | EH4 7EA | country:gb | - | gb | E4 7EA | country:gb | - When sending search query "EH4 7EA" - Then results contain - | type | display_name | - | postcode | EH4 7EA, United Kingdom | - When sending search query "E4 7EA" - Then results contain - | type | display_name | - | postcode | E4 7EA, United Kingdom | - - - Scenario: Postcode areas are preferred over postcode points - Given the grid with origin DE - | 1 | 2 | - | 4 | 3 | - Given the places - | osm | class | type | postcode | geometry | - | R23 | boundary | postal_code | 12345 | (1,2,3,4,1) | - When importing - Then location_postcode contains exactly - | country | postcode | - | de | 12345 | - When sending search query "12345, de" - Then results contain - | osm | - | R23 | diff --git a/test/bdd/db/query/reverse.feature b/test/bdd/db/query/reverse.feature deleted file mode 100644 index 11ee8685..00000000 --- a/test/bdd/db/query/reverse.feature +++ /dev/null @@ -1,22 +0,0 @@ -@DB -Feature: Reverse searches - Test results of reverse queries - - Scenario: POI in POI area - Given the 0.0001 grid with origin 1,1 - | 1 | | | | | | | | 2 | - | | 9 | | | | | | | | - | 4 | | | | | | | | 3 | - And the places - | osm | class | type | geometry | - | W1 | aeroway | terminal | (1,2,3,4,1) | - | N1 | amenity | restaurant | 9 | - When importing - And sending v1/reverse at 1.0001,1.0001 - Then results contain - | osm | - | N1 | - When sending v1/reverse at 1.0003,1.0001 - Then results contain - | osm | - | W1 | diff --git a/test/bdd/db/query/search_simple.feature b/test/bdd/db/query/search_simple.feature deleted file mode 100644 index 5fef3132..00000000 --- a/test/bdd/db/query/search_simple.feature +++ /dev/null @@ -1,108 +0,0 @@ -@DB -Feature: Searching of simple objects - Testing simple stuff - - Scenario: Search for place node - Given the places - | osm | class | type | name+name | geometry | - | N1 | place | village | Foo | 10.0 -10.0 | - When importing - And sending search query "Foo" - Then results contain - | ID | osm | category | type | centroid | - | 0 | N1 | place | village | 10 -10 | - - Scenario: Updating postcode in postcode boundaries without ref - Given the grid - | 1 | 2 | - | 4 | 3 | - Given the places - | osm | class | type | postcode | geometry | - | R1 | boundary | postal_code | 12345 | (1,2,3,4,1) | - When importing - And sending search query "12345" - Then results contain - | ID | osm | - | 0 | R1 | - When updating places - | osm | class | type | postcode | geometry | - | R1 | boundary | postal_code | 54321 | (1,2,3,4,1) | - And sending search query "12345" - Then exactly 0 results are returned - When sending search query "54321" - Then results contain - | ID | osm | - | 0 | R1 | - - # github #1763 - Scenario: Correct translation of highways under construction - Given the grid - | 1 | | | | 2 | - | | | 9 | | | - And the places - | osm | class | type | name | geometry | - | W1 | highway | construction | The build | 1,2 | - | N1 | amenity | cafe | Bean | 9 | - When importing - And sending json search query "Bean" with address - Then result addresses contain - | amenity | road | - | Bean | The build | - - Scenario: when missing housenumbers in search don't return a POI - Given the places - | osm | class | type | name | - | N3 | amenity | restaurant | Wood Street | - And the places - | osm | class | type | name | housenr | - | N20 | amenity | restaurant | Red Way | 34 | - When importing - And sending search query "Wood Street 45" - Then exactly 0 results are returned - When sending search query "Red Way 34" - Then results contain - | osm | - | N20 | - - Scenario: when the housenumber is missing the street is still returned - Given the grid - | 1 | | 2 | - Given the places - | osm | class | type | name | geometry | - | W1 | highway | residential | Wood Street | 1, 2 | - When importing - And sending search query "Wood Street" - Then results contain - | osm | - | W1 | - - - Scenario Outline: Special cased american states will be found - Given the grid - | 1 | | 2 | - | | 10 | | - | 4 | | 3 | - Given the places - | osm | class | type | admin | name | name+ref | geometry | - | R1 | boundary | administrative | 4 | | | (1,2,3,4,1) | - Given the places - | osm | class | type | name | geometry | - | N2 | place | town | | 10 | - | N3 | place | city | | country:ca | - When importing - And sending search query ", " - Then results contain - | osm | - | N2 | - When sending search query ", " - | accept-language | - | en | - Then results contain - | osm | - | N2 | - - Examples: - | city | state | ref | - | Chicago | Illinois | IL | - | Auburn | Alabama | AL | - | New Orleans | Louisiana | LA | diff --git a/test/bdd/db/update/country.feature b/test/bdd/db/update/country.feature deleted file mode 100644 index abc1af09..00000000 --- a/test/bdd/db/update/country.feature +++ /dev/null @@ -1,109 +0,0 @@ -@DB -Feature: Country handling - Tests for update of country information - - Background: - Given the 1.0 grid with origin DE - | 1 | | 2 | - | | 10 | | - | 4 | | 3 | - - Scenario: When country names are changed old ones are no longer searchable - Given the places - | osm | class | type | admin | name+name:xy | country | geometry | - | R1 | boundary | administrative | 2 | Loudou | de | (1,2,3,4,1) | - Given the places - | osm | class | type | name | - | N10 | place | town | Wenig | - When importing - When sending search query "Wenig, Loudou" - Then results contain - | osm | - | N10 | - When updating places - | osm | class | type | admin | name+name:xy | country | geometry | - | R1 | boundary | administrative | 2 | Germany | de | (1,2,3,4,1) | - When sending search query "Wenig, Loudou" - Then exactly 0 results are returned - - Scenario: When country names are deleted they are no longer searchable - Given the places - | osm | class | type | admin | name+name:xy | country | geometry | - | R1 | boundary | administrative | 2 | Loudou | de | (1,2,3,4,1) | - Given the places - | osm | class | type | name | - | N10 | place | town | Wenig | - When importing - When sending search query "Wenig, Loudou" - Then results contain - | osm | - | N10 | - When updating places - | osm | class | type | admin | name+name:en | country | geometry | - | R1 | boundary | administrative | 2 | Germany | de | (1,2,3,4,1) | - When sending search query "Wenig, Loudou" - Then exactly 0 results are returned - When sending search query "Wenig" - | accept-language | - | xy,en | - Then results contain - | osm | display_name | - | N10 | Wenig, Germany | - - - Scenario: Default country names are always searchable - Given the places - | osm | class | type | name | - | N10 | place | town | Wenig | - When importing - When sending search query "Wenig, Germany" - Then results contain - | osm | - | N10 | - When sending search query "Wenig, de" - Then results contain - | osm | - | N10 | - When updating places - | osm | class | type | admin | name+name:en | country | geometry | - | R1 | boundary | administrative | 2 | Lilly | de | (1,2,3,4,1) | - When sending search query "Wenig, Germany" - | accept-language | - | en,de | - Then results contain - | osm | display_name | - | N10 | Wenig, Lilly | - When sending search query "Wenig, de" - | accept-language | - | en,de | - Then results contain - | osm | display_name | - | N10 | Wenig, Lilly | - - - Scenario: When a localised name is deleted, the standard name takes over - Given the places - | osm | class | type | admin | name+name:de | country | geometry | - | R1 | boundary | administrative | 2 | Loudou | de | (1,2,3,4,1) | - Given the places - | osm | class | type | name | - | N10 | place | town | Wenig | - When importing - When sending search query "Wenig, Loudou" - | accept-language | - | de,en | - Then results contain - | osm | display_name | - | N10 | Wenig, Loudou | - When updating places - | osm | class | type | admin | name+name:en | country | geometry | - | R1 | boundary | administrative | 2 | Germany | de | (1,2,3,4,1) | - When sending search query "Wenig, Loudou" - Then exactly 0 results are returned - When sending search query "Wenig" - | accept-language | - | de,en | - Then results contain - | osm | display_name | - | N10 | Wenig, Deutschland | - diff --git a/test/bdd/db/update/interpolation.feature b/test/bdd/db/update/interpolation.feature deleted file mode 100644 index 421fdc01..00000000 --- a/test/bdd/db/update/interpolation.feature +++ /dev/null @@ -1,419 +0,0 @@ -@DB -Feature: Update of address interpolations - Test the interpolated address are updated correctly - - Scenario: new interpolation added to existing street - Given the grid - | 10 | | | | 11 | - | | 1 | 99 | 2 | | - | | | | | | - | 20 | | | | 21 | - And the places - | osm | class | type | name | geometry | - | W2 | highway | unclassified | Sun Way | 10,11 | - | W3 | highway | unclassified | Cloud Street | 20,21 | - And the ways - | id | nodes | - | 10 | 1,2 | - When importing - Then W10 expands to no interpolation - When updating places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 6 | - And updating places - | osm | class | type | addr+interpolation | geometry | - | W10 | place | houses | even | 1,2 | - Then placex contains - | object | parent_place_id | - | N1 | W2 | - | N2 | W2 | - And W10 expands to interpolation - | parent_place_id | start | end | geometry | - | W2 | 4 | 4 | 99 | - - Scenario: addr:street added to interpolation - Given the grid - | 10 | | | | 11 | - | | 1 | | 2 | | - | | | | | | - | 20 | | | | 21 | - And the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 6 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W10 | place | houses | even | 1,2 | - And the places - | osm | class | type | name | geometry | - | W2 | highway | unclassified | Sun Way | 10,11 | - | W3 | highway | unclassified | Cloud Street | 20,21 | - And the ways - | id | nodes | - | 10 | 1,2 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W2 | - | N2 | W2 | - And W10 expands to interpolation - | parent_place_id | start | end | - | W2 | 4 | 4 | - When updating places - | osm | class | type | addr+interpolation | street | geometry | - | W10 | place | houses | even | Cloud Street | 1,2 | - Then placex contains - | object | parent_place_id | - | N1 | W3 | - | N2 | W3 | - And W10 expands to interpolation - | parent_place_id | start | end | - | W3 | 4 | 4 | - - Scenario: addr:street added to housenumbers - Given the grid - | 10 | | | | 11 | - | | 1 | | 2 | | - | | | | | | - | 20 | | | | 21 | - And the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 6 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W10 | place | houses | even | 1,2 | - And the places - | osm | class | type | name | geometry | - | W2 | highway | unclassified | Sun Way | 10,11 | - | W3 | highway | unclassified | Cloud Street | 20,21 | - And the ways - | id | nodes | - | 10 | 1,2 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W2 | - | N2 | W2 | - And W10 expands to interpolation - | parent_place_id | start | end | - | W2 | 4 | 4 | - When updating places - | osm | class | type | street | housenr | - | N1 | place | house | Cloud Street| 2 | - | N2 | place | house | Cloud Street| 6 | - Then placex contains - | object | parent_place_id | - | N1 | W3 | - | N2 | W3 | - And W10 expands to interpolation - | parent_place_id | start | end | - | W3 | 4 | 4 | - - Scenario: interpolation tag removed - Given the grid - | 10 | | | | 11 | - | | 1 | | 2 | | - | | | | | | - | 20 | | | | 21 | - And the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 6 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W10 | place | houses | even | 1,2 | - And the places - | osm | class | type | name | geometry | - | W2 | highway | unclassified | Sun Way | 10,11 | - | W3 | highway | unclassified | Cloud Street | 20,21 | - And the ways - | id | nodes | - | 10 | 1,2 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W2 | - | N2 | W2 | - And W10 expands to interpolation - | parent_place_id | start | end | - | W2 | 4 | 4 | - When marking for delete W10 - Then W10 expands to no interpolation - And placex contains - | object | parent_place_id | - | N1 | W2 | - | N2 | W2 | - - Scenario: referenced road added - Given the grid - | 10 | | | | 11 | - | | 1 | | 2 | | - | | | | | | - | 20 | | | | 21 | - And the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 6 | - And the places - | osm | class | type | addr+interpolation | street | geometry | - | W10 | place | houses | even | Cloud Street| 1,2 | - And the places - | osm | class | type | name | geometry | - | W2 | highway | unclassified | Sun Way | 10,11 | - And the ways - | id | nodes | - | 10 | 1,2 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W2 | - | N2 | W2 | - And W10 expands to interpolation - | parent_place_id | start | end | - | W2 | 4 | 4 | - When updating places - | osm | class | type | name | geometry | - | W3 | highway | unclassified | Cloud Street | 20,21 | - Then placex contains - | object | parent_place_id | - | N1 | W3 | - | N2 | W3 | - And W10 expands to interpolation - | parent_place_id | start | end | - | W3 | 4 | 4 | - - Scenario: referenced road deleted - Given the grid - | 10 | | | | 11 | - | | 1 | | 2 | | - | | | | | | - | 20 | | | | 21 | - And the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 6 | - And the places - | osm | class | type | addr+interpolation | street | geometry | - | W10 | place | houses | even | Cloud Street| 1,2 | - And the places - | osm | class | type | name | geometry | - | W2 | highway | unclassified | Sun Way | 10,11 | - | W3 | highway | unclassified | Cloud Street | 20,21 | - And the ways - | id | nodes | - | 10 | 1,2 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W3 | - | N2 | W3 | - And W10 expands to interpolation - | parent_place_id | start | end | - | W3 | 4 | 4 | - When marking for delete W3 - Then placex contains - | object | parent_place_id | - | N1 | W2 | - | N2 | W2 | - And W10 expands to interpolation - | parent_place_id | start | end | - | W2 | 4 | 4 | - - Scenario: building becomes interpolation - Given the grid - | 10 | | | | 11 | - | | 1 | | 2 | | - | | 4 | | 3 | | - And the places - | osm | class | type | housenr | geometry | - | W1 | place | house | 3 | (1,2,3,4,1) | - And the places - | osm | class | type | name | geometry | - | W2 | highway | unclassified | Cloud Street | 10,11 | - When importing - Then placex contains - | object | parent_place_id | - | W1 | W2 | - Given the ways - | id | nodes | - | 1 | 1,2 | - When updating places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 6 | - And updating places - | osm | class | type | addr+interpolation | street | geometry | - | W1 | place | houses | even | Cloud Street| 1,2 | - Then placex has no entry for W1 - And W1 expands to interpolation - | parent_place_id | start | end | - | W2 | 4 | 4 | - - Scenario: interpolation becomes building - Given the grid - | 10 | | | | 11 | - | | 1 | | 2 | | - | | 4 | | 3 | | - And the places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 6 | - And the places - | osm | class | type | name | geometry | - | W2 | highway | unclassified | Cloud Street | 10,11 | - And the ways - | id | nodes | - | 1 | 1,2 | - And the places - | osm | class | type | addr+interpolation | street | geometry | - | W1 | place | houses | even | Cloud Street| 1,2 | - When importing - Then placex has no entry for W1 - And W1 expands to interpolation - | parent_place_id | start | end | - | W2 | 4 | 4 | - When updating places - | osm | class | type | housenr | geometry | - | W1 | place | house | 3 | (1,2,3,4,1) | - Then placex contains - | object | parent_place_id | - | W1 | W2 | - And W1 expands to no interpolation - - Scenario: housenumbers added to interpolation - Given the grid - | 10 | | | | 11 | - | | 1 | | 2 | | - And the places - | osm | class | type | name | geometry | - | W2 | highway | unclassified | Cloud Street | 10,11 | - And the ways - | id | nodes | - | 1 | 1,2 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W1 | place | houses | even | 1,2 | - When importing - Then W1 expands to no interpolation - When updating places - | osm | class | type | housenr | - | N1 | place | house | 2 | - | N2 | place | house | 6 | - Then W1 expands to interpolation - | parent_place_id | start | end | - | W2 | 4 | 4 | - - Scenario: housenumber added in middle of interpolation - Given the grid - | 1 | | | | | 2 | - | 3 | | | 4 | | 5 | - And the places - | osm | class | type | name | geometry | - | W1 | highway | unclassified | Cloud Street | 1, 2 | - And the ways - | id | nodes | - | 2 | 3,4,5 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W2 | place | houses | even | 3,4,5 | - And the places - | osm | class | type | housenr | - | N3 | place | house | 2 | - | N5 | place | house | 10 | - When importing - Then W2 expands to interpolation - | parent_place_id | start | end | - | W1 | 4 | 8 | - When updating places - | osm | class | type | housenr | - | N4 | place | house | 6 | - Then W2 expands to interpolation - | parent_place_id | start | end | - | W1 | 4 | 4 | - | W1 | 8 | 8 | - - @Fail - Scenario: housenumber removed in middle of interpolation - Given the grid - | 1 | | | | | 2 | - | 3 | | | 4 | | 5 | - And the places - | osm | class | type | name | geometry | - | W1 | highway | unclassified | Cloud Street | 1, 2 | - And the ways - | id | nodes | - | 2 | 3,4,5 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W2 | place | houses | even | 3,4,5 | - And the places - | osm | class | type | housenr | - | N3 | place | house | 2 | - | N4 | place | house | 6 | - | N5 | place | house | 10 | - When importing - Then W2 expands to interpolation - | parent_place_id | start | end | - | W1 | 4 | 4 | - | W1 | 8 | 8 | - When marking for delete N4 - Then W2 expands to interpolation - | parent_place_id | start | end | - | W1 | 4 | 8 | - - Scenario: Change the start housenumber - Given the grid - | 1 | | 2 | - | 3 | | 4 | - And the places - | osm | class | type | name | geometry | - | W1 | highway | unclassified | Cloud Street | 1, 2 | - And the ways - | id | nodes | - | 2 | 3,4 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W2 | place | houses | even | 3,4 | - And the places - | osm | class | type | housenr | - | N3 | place | house | 2 | - | N4 | place | house | 6 | - When importing - Then W2 expands to interpolation - | parent_place_id | start | end | - | W1 | 4 | 4 | - When updating places - | osm | class | type | housenr | - | N4 | place | house | 8 | - Then W2 expands to interpolation - | parent_place_id | start | end | - | W1 | 4 | 6 | - - Scenario: Legal interpolation type changed to illegal one - Given the grid - | 1 | | 2 | - | 3 | | 4 | - And the places - | osm | class | type | name | geometry | - | W1 | highway | unclassified | Cloud Street | 1, 2 | - And the ways - | id | nodes | - | 2 | 3,4 | - And the places - | osm | class | type | addr+interpolation | geometry | - | W2 | place | houses | even | 3,4 | - And the places - | osm | class | type | housenr | - | N3 | place | house | 2 | - | N4 | place | house | 6 | - When importing - Then W2 expands to interpolation - | parent_place_id | start | end | - | W1 | 4 | 4 | - When updating places - | osm | class | type | addr+interpolation | geometry | - | W2 | place | houses | 12-2 | 3,4 | - Then W2 expands to no interpolation - diff --git a/test/bdd/db/update/linked_places.feature b/test/bdd/db/update/linked_places.feature deleted file mode 100644 index d6370ebb..00000000 --- a/test/bdd/db/update/linked_places.feature +++ /dev/null @@ -1,341 +0,0 @@ -@DB -Feature: Updates of linked places - Tests that linked places are correctly added and deleted. - - Scenario: Linking is kept when boundary is updated - Given the 0.1 grid - | 10 | | 11 | - | | 1 | | - | 13 | | 12 | - Given the places - | osm | class | type | name | - | N1 | place | city | foo | - And the places - | osm | class | type | name | admin | geometry | - | R1 | boundary | administrative | foo | 8 | (10,11,12,13,10) | - When importing - Then placex contains - | object | linked_place_id | - | N1 | R1 | - When updating places - | osm | class | type | name | name+name:de | admin | geometry | - | R1 | boundary | administrative | foo | Dingens | 8 | (10,11,12,13,10) | - Then placex contains - | object | linked_place_id | - | N1 | R1 | - - - Scenario: Add linked place when linking relation is renamed - Given the 0.1 grid - | 10 | | 11 | - | | 1 | | - | 13 | | 12 | - Given the places - | osm | class | type | name | - | N1 | place | city | foo | - And the places - | osm | class | type | name | admin | geometry | - | R1 | boundary | administrative | foo | 8 | (10,11,12,13,10) | - When importing - Then placex contains - | object | linked_place_id | - | N1 | R1 | - When sending search query "foo" - | dups | - | 1 | - Then results contain - | osm | - | R1 | - When updating places - | osm | class | type | name | admin | geometry | - | R1 | boundary | administrative | foobar | 8 | (10,11,12,13,10) | - Then placex contains - | object | linked_place_id | - | N1 | - | - When sending search query "foo" - | dups | - | 1 | - Then results contain - | osm | - | N1 | - - Scenario: Add linked place when linking relation is removed - Given the 0.1 grid - | 10 | | 11 | - | | 1 | | - | 13 | | 12 | - Given the places - | osm | class | type | name | - | N1 | place | city | foo | - And the places - | osm | class | type | name | admin | geometry | - | R1 | boundary | administrative | foo | 8 | (10,11,12,13,10) | - When importing - And sending search query "foo" - | dups | - | 1 | - Then results contain - | osm | - | R1 | - When marking for delete R1 - Then placex contains - | object | linked_place_id | - | N1 | - | - When sending search query "foo" - | dups | - | 1 | - Then results contain - | osm | - | N1 | - - Scenario: Remove linked place when linking relation is added - Given the 0.1 grid - | 10 | | 11 | - | | 1 | | - | 13 | | 12 | - Given the places - | osm | class | type | name | - | N1 | place | city | foo | - When importing - And sending search query "foo" - | dups | - | 1 | - Then results contain - | osm | - | N1 | - When updating places - | osm | class | type | name | admin | geometry | - | R1 | boundary | administrative | foo | 8 | (10,11,12,13,10) | - Then placex contains - | object | linked_place_id | - | N1 | R1 | - When sending search query "foo" - | dups | - | 1 | - Then results contain - | osm | - | R1 | - - Scenario: Remove linked place when linking relation is renamed - Given the 0.1 grid - | 10 | | 11 | - | | 1 | | - | 13 | | 12 | - Given the places - | osm | class | type | name | - | N1 | place | city | foo | - And the places - | osm | class | type | name | admin | geometry | - | R1 | boundary | administrative | foobar | 8 | (10,11,12,13,10) | - When importing - And sending search query "foo" - | dups | - | 1 | - Then results contain - | osm | - | N1 | - When updating places - | osm | class | type | name | admin | geometry | - | R1 | boundary | administrative | foo | 8 | (10,11,12,13,10) | - Then placex contains - | object | linked_place_id | - | N1 | R1 | - When sending search query "foo" - | dups | - | 1 | - Then results contain - | osm | - | R1 | - - Scenario: Update linking relation when linkee name is updated - Given the 0.1 grid - | 10 | | 11 | - | | 3 | | - | 13 | | 12 | - Given the places - | osm | class | type | name | admin | geometry | - | R1 | boundary | administrative | rel | 8 | (10,11,12,13,10) | - And the places - | osm | class | type | name+name:de | - | N3 | place | city | greeny | - And the relations - | id | members | - | 1 | N3:label | - When importing - Then placex contains - | object | linked_place_id | name+_place_name:de | - | R1 | - | greeny | - And placex contains - | object | linked_place_id | name+name:de | - | N3 | R1 | greeny | - When updating places - | osm | class | type | name+name:de | - | N3 | place | city | newname | - Then placex contains - | object | linked_place_id | name+name:de | - | N3 | R1 | newname | - And placex contains - | object | linked_place_id | name+_place_name:de | - | R1 | - | newname | - - Scenario: Update linking relation when linkee name is deleted - Given the 0.1 grid - | 10 | | 11 | - | | 3 | | - | 13 | | 12 | - Given the places - | osm | class | type | name | admin | geometry | - | R1 | boundary | administrative | rel | 8 | (10,11,12,13,10) | - And the places - | osm | class | type | name | - | N3 | place | city | greeny | - And the relations - | id | members | - | 1 | N3:label | - When importing - Then placex contains - | object | linked_place_id | name+_place_name | name+name | - | R1 | - | greeny | rel | - And placex contains - | object | linked_place_id | name+name | - | N3 | R1 | greeny | - When sending search query "greeny" - Then results contain - | osm | - | R1 | - When updating places - | osm | class | type | name+name:de | - | N3 | place | city | depnt | - Then placex contains - | object | linked_place_id | name+name:de | - | N3 | R1 | depnt | - And placex contains - | object | linked_place_id | name+_place_name:de | name+name | - | R1 | - | depnt | rel | - When sending search query "greeny" - Then exactly 0 results are returned - - Scenario: Updating linkee extratags keeps linker's extratags - Given the 0.1 grid - | 10 | | 11 | - | | 3 | | - | 13 | | 12 | - Given the named places - | osm | class | type | extra+wikidata | admin | geometry | - | R1 | boundary | administrative | 34 | 8 | (10,11,12,13,10) | - And the named places - | osm | class | type | - | N3 | place | city | - And the relations - | id | members | - | 1 | N3:label | - When importing - Then placex contains - | object | extratags | - | R1 | 'wikidata' : '34', 'linked_place' : 'city' | - When updating places - | osm | class | type | name | extra+oneway | - | N3 | place | city | newname | yes | - Then placex contains - | object | extratags | - | R1 | 'wikidata' : '34', 'oneway' : 'yes', 'linked_place' : 'city' | - - Scenario: Remove linked_place info when linkee is removed - Given the 0.1 grid - | 10 | | 11 | - | | 1 | | - | 13 | | 12 | - Given the places - | osm | class | type | name | - | N1 | place | city | foo | - And the places - | osm | class | type | name | admin | geometry | - | R1 | boundary | administrative | foo | 8 | (10,11,12,13,10) | - When importing - Then placex contains - | object | extratags | - | R1 | 'linked_place' : 'city' | - When marking for delete N1 - Then placex contains - | object | extratags | - | R1 | - | - - Scenario: Update linked_place info when linkee type changes - Given the 0.1 grid - | 10 | | 11 | - | | 1 | | - | 13 | | 12 | - Given the places - | osm | class | type | name | - | N1 | place | city | foo | - And the places - | osm | class | type | name | admin | geometry | - | R1 | boundary | administrative | foo | 8 | (10,11,12,13,10) | - When importing - Then placex contains - | object | extratags | - | R1 | 'linked_place' : 'city' | - When updating places - | osm | class | type | name | - | N1 | place | town | foo | - Then placex contains - | object | extratags | - | R1 | 'linked_place' : 'town' | - - - Scenario: Keep linking and ranks when place type changes - Given the grid - | 1 | | | 2 | - | | | 9 | | - | 4 | | | 3 | - And the places - | osm | class | type | name | admin | geometry | - | R1 | boundary | administrative | foo | 8 | (1,2,3,4,1) | - And the places - | osm | class | type | name | geometry | - | N1 | place | city | foo | 9 | - When importing - Then placex contains - | object | linked_place_id | rank_address | - | N1 | R1 | 16 | - | R1 | - | 16 | - - When updating places - | osm | class | type | name | geometry | - | N1 | place | town | foo | 9 | - Then placex contains - | object | linked_place_id | rank_address | - | N1 | R1 | 16 | - | R1 | - | 16 | - - - Scenario: Invalidate surrounding place nodes when place type changes - Given the grid - | 1 | | | 2 | - | | 8 | 9 | | - | 4 | | | 3 | - And the places - | osm | class | type | name | admin | geometry | - | R1 | boundary | administrative | foo | 8 | (1,2,3,4,1) | - And the places - | osm | class | type | name | geometry | - | N1 | place | town | foo | 9 | - | N2 | place | city | bar | 8 | - And the relations - | id | members | - | 1 | N1:label | - When importing - Then placex contains - | object | linked_place_id | rank_address | - | N1 | R1 | 16 | - | R1 | - | 16 | - | N2 | - | 18 | - - When updating places - | osm | class | type | name | geometry | - | N1 | place | suburb | foo | 9 | - Then placex contains - | object | linked_place_id | rank_address | - | N1 | R1 | 20 | - | R1 | - | 20 | - | N2 | - | 16 | diff --git a/test/bdd/db/update/naming.feature b/test/bdd/db/update/naming.feature deleted file mode 100644 index 6c1a817b..00000000 --- a/test/bdd/db/update/naming.feature +++ /dev/null @@ -1,21 +0,0 @@ -@DB -Feature: Update of names in place objects - Test all naming related issues in updates - - Scenario: Delete postcode from postcode boundaries without ref - Given the grid with origin DE - | 1 | 2 | - | 4 | 3 | - Given the places - | osm | class | type | postcode | geometry | - | R1 | boundary | postal_code | 123-45 | (1,2,3,4,1) | - When importing - And sending search query "123-45" - Then results contain - | ID | osm | - | 0 | R1 | - When updating places - | osm | class | type | geometry | - | R1 | boundary | postal_code | (1,2,3,4,1) | - Then placex has no entry for R1 - diff --git a/test/bdd/db/update/parenting.feature b/test/bdd/db/update/parenting.feature deleted file mode 100644 index 1a23d903..00000000 --- a/test/bdd/db/update/parenting.feature +++ /dev/null @@ -1,164 +0,0 @@ -@DB -Feature: Update parenting of objects - - Scenario: POI inside building inherits addr:street change - Given the grid - | 10 | | | | | | | 11 | - | | | 5 | | | 6 | | | - | | | | | | | | | - | | | | | 1 | | | | - | 12 | | 8 | | | 7 | | | - And the named places - | osm | class | type | - | N1 | amenity | bank | - And the places - | osm | class | type | street | housenr | geometry | - | W1 | building | yes | nowhere | 3 | (5,6,7,8,5) | - And the places - | osm | class | type | name | geometry | - | W2 | highway | primary | bar | 10,11 | - | W3 | highway | residential | foo | 10,12 | - When importing - Then placex contains - | object | parent_place_id | housenumber | - | W1 | W2 | 3 | - | N1 | W2 | 3 | - When updating places - | osm | class | type | street | addr_place | housenr | geometry | - | W1 | building | yes | foo | nowhere | 3 | (5,6,7,8,5) | - And updating places - | osm | class | type | name | - | N1 | amenity | bank | well | - Then placex contains - | object | parent_place_id | housenumber | - | W1 | W3 | 3 | - | N1 | W3 | 3 | - - - Scenario: Housenumber is reparented when street gets name matching addr:street - Given the grid - | 1 | | | 2 | - | | 10 | | | - | | | | | - | 3 | | | 4 | - And the places - | osm | class | type | name | geometry | - | W1 | highway | residential | A street | 1,2 | - | W2 | highway | residential | B street | 3,4 | - And the places - | osm | class | type | housenr | street | geometry | - | N1 | building | yes | 3 | X street | 10 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W1 | - When updating places - | osm | class | type | name | geometry | - | W2 | highway | residential | X street | 3,4 | - Then placex contains - | object | parent_place_id | - | N1 | W2 | - - - Scenario: Housenumber is reparented when street looses name matching addr:street - Given the grid - | 1 | | | 2 | - | | 10 | | | - | | | | | - | 3 | | | 4 | - And the places - | osm | class | type | name | geometry | - | W1 | highway | residential | A street | 1,2 | - | W2 | highway | residential | X street | 3,4 | - And the places - | osm | class | type | housenr | street | geometry | - | N1 | building | yes | 3 | X street | 10 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W2 | - When updating places - | osm | class | type | name | geometry | - | W2 | highway | residential | B street | 3,4 | - Then placex contains - | object | parent_place_id | - | N1 | W1 | - - - Scenario: Housenumber is reparented when street gets name matching addr:street - Given the grid - | 1 | | | 2 | - | | 10 | | | - | | | | | - | 3 | | | 4 | - And the places - | osm | class | type | name | geometry | - | W1 | highway | residential | A street | 1,2 | - | W2 | highway | residential | B street | 3,4 | - And the places - | osm | class | type | housenr | street | geometry | - | N1 | building | yes | 3 | X street | 10 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | W1 | - When updating places - | osm | class | type | name | geometry | - | W2 | highway | residential | X street | 3,4 | - Then placex contains - | object | parent_place_id | - | N1 | W2 | - - - # Invalidation of geometries currently disabled for addr:place matches. - @Fail - Scenario: Housenumber is reparented when place is renamed to matching addr:place - Given the grid - | 1 | | | 2 | - | | 10 | 4 | | - | | | | | - | | | 5 | | - And the places - | osm | class | type | name | geometry | - | W1 | highway | residential | A street | 1,2 | - | N5 | place | village | Bdorf | 5 | - | N4 | place | village | Other | 4 | - And the places - | osm | class | type | housenr | addr_place | geometry | - | N1 | building | yes | 3 | Cdorf | 10 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | N4 | - When updating places - | osm | class | type | name | geometry | - | N5 | place | village | Cdorf | 5 | - Then placex contains - | object | parent_place_id | - | N1 | N5 | - - - Scenario: Housenumber is reparented when it looses a matching addr:place - Given the grid - | 1 | | | 2 | - | | 10 | 4 | | - | | | | | - | | | 5 | | - And the places - | osm | class | type | name | geometry | - | W1 | highway | residential | A street | 1,2 | - | N5 | place | village | Bdorf | 5 | - | N4 | place | village | Other | 4 | - And the places - | osm | class | type | housenr | addr_place | geometry | - | N1 | building | yes | 3 | Bdorf | 10 | - When importing - Then placex contains - | object | parent_place_id | - | N1 | N5 | - When updating places - | osm | class | type | name | geometry | - | N5 | place | village | Cdorf | 5 | - Then placex contains - | object | parent_place_id | - | N1 | N4 | diff --git a/test/bdd/db/update/postcode.feature b/test/bdd/db/update/postcode.feature deleted file mode 100644 index 61b52f3d..00000000 --- a/test/bdd/db/update/postcode.feature +++ /dev/null @@ -1,119 +0,0 @@ -@DB -Feature: Update of postcode - Tests for updating of data related to postcodes - - Scenario: A new postcode appears in the postcode table - Given the places - | osm | class | type | addr+postcode | addr+housenumber | geometry | - | N34 | place | house | 01982 | 111 |country:de | - When importing - Then location_postcode contains exactly - | country | postcode | geometry | - | de | 01982 | country:de | - When updating places - | osm | class | type | addr+postcode | addr+housenumber | geometry | - | N35 | place | house | 4567 | 5 |country:ch | - And updating postcodes - Then location_postcode contains exactly - | country | postcode | geometry | - | de | 01982 | country:de | - | ch | 4567 | country:ch | - - Scenario: When the last postcode is deleted, it is deleted from postcode - Given the places - | osm | class | type | addr+postcode | addr+housenumber | geometry | - | N34 | place | house | 01982 | 111 |country:de | - | N35 | place | house | 4567 | 5 |country:ch | - When importing - And marking for delete N34 - And updating postcodes - Then location_postcode contains exactly - | country | postcode | geometry | - | ch | 4567 | country:ch | - - Scenario: A postcode is not deleted from postcode when it exist in another country - Given the places - | osm | class | type | addr+postcode | addr+housenumber | geometry | - | N34 | place | house | 01982 | 111 |country:de | - | N35 | place | house | 01982 | 5 |country:fr | - When importing - And marking for delete N34 - And updating postcodes - Then location_postcode contains exactly - | country | postcode | geometry | - | fr | 01982 | country:fr | - - Scenario: Updating a postcode is reflected in postcode table - Given the places - | osm | class | type | addr+postcode | geometry | - | N34 | place | postcode | 01982 | country:de | - When importing - And updating places - | osm | class | type | addr+postcode | geometry | - | N34 | place | postcode | 20453 | country:de | - And updating postcodes - Then location_postcode contains exactly - | country | postcode | geometry | - | de | 20453 | country:de | - - Scenario: When changing from a postcode type, the entry appears in placex - When importing - And updating places - | osm | class | type | addr+postcode | geometry | - | N34 | place | postcode | 01982 | country:de | - Then placex has no entry for N34 - When updating places - | osm | class | type | addr+postcode | housenr | geometry | - | N34 | place | house | 20453 | 1 | country:de | - Then placex contains - | object | addr+housenumber | geometry | - | N34 | 1 | country:de| - And place contains exactly - | object | class | type | - | N34 | place | house | - When updating postcodes - Then location_postcode contains exactly - | country | postcode | geometry | - | de | 20453 | country:de | - - Scenario: When changing to a postcode type, the entry disappears from placex - When importing - And updating places - | osm | class | type | addr+postcode | housenr | geometry | - | N34 | place | house | 20453 | 1 | country:de | - Then placex contains - | object | addr+housenumber | geometry | - | N34 | 1 | country:de| - When updating places - | osm | class | type | addr+postcode | geometry | - | N34 | place | postcode | 01982 | country:de | - Then placex has no entry for N34 - And place contains exactly - | object | class | type | - | N34 | place | postcode | - When updating postcodes - Then location_postcode contains exactly - | country | postcode | geometry | - | de | 01982 | country:de | - - Scenario: When a parent is deleted, the postcode gets a new parent - Given the grid with origin DE - | 1 | | 3 | 4 | - | | 9 | | | - | 2 | | 5 | 6 | - Given the places - | osm | class | type | name | admin | geometry | - | R1 | boundary | administrative | Big | 6 | (1,4,6,2,1) | - | R2 | boundary | administrative | Small | 6 | (1,3,5,2,1) | - Given the named places - | osm | class | type | addr+postcode | geometry | - | N9 | place | postcode | 12345 | 9 | - When importing - And updating postcodes - Then location_postcode contains exactly - | country | postcode | geometry | parent_place_id | - | de | 12345 | 9 | R2 | - When marking for delete R2 - Then location_postcode contains exactly - | country | postcode | geometry | parent_place_id | - | de | 12345 | 9 | R1 | diff --git a/test/bdd/db/update/simple.feature b/test/bdd/db/update/simple.feature deleted file mode 100644 index 73abcd22..00000000 --- a/test/bdd/db/update/simple.feature +++ /dev/null @@ -1,116 +0,0 @@ -@DB -Feature: Update of simple objects - Testing simple updating functionality - - Scenario: Do delete small boundary features - Given the 1.0 grid - | 1 | 2 | - | 4 | 3 | - Given the places - | osm | class | type | admin | geometry | - | R1 | boundary | administrative | 3 | (1,2,3,4,1) | - When importing - Then placex contains - | object | rank_search | - | R1 | 6 | - When marking for delete R1 - Then placex has no entry for R1 - - Scenario: Do not delete large boundary features - Given the 2.0 grid - | 1 | 2 | - | 4 | 3 | - Given the places - | osm | class | type | admin | geometry | - | R1 | boundary | administrative | 3 | (1,2,3,4,1) | - When importing - Then placex contains - | object | rank_search | - | R1 | 6 | - When marking for delete R1 - Then placex contains - | object | rank_search | - | R1 | 6 | - - Scenario: Do delete large features of low rank - Given the 2.0 grid - | 1 | 2 | - | 4 | 3 | - Given the named places - | osm | class | type | geometry | - | W1 | place | house | (1,2,3,4,1) | - | R1 | natural | wood | (1,2,3,4,1) | - | R2 | highway | residential | (1,2,3,4,1) | - When importing - Then placex contains - | object | rank_address | - | R1 | 0 | - | R2 | 26 | - | W1 | 30 | - When marking for delete R1,R2,W1 - Then placex has no entry for W1 - Then placex has no entry for R1 - Then placex has no entry for R2 - - Scenario: type mutation - Given the places - | osm | class | type | geometry | - | N3 | shop | toys | 1 -1 | - When importing - Then placex contains - | object | class | type | centroid | - | N3 | shop | toys | 1 -1 | - When updating places - | osm | class | type | geometry | - | N3 | shop | grocery | 1 -1 | - Then placex contains - | object | class | type | centroid | - | N3 | shop | grocery | 1 -1 | - - Scenario: remove postcode place when house number is added - Given the places - | osm | class | type | postcode | geometry | - | N3 | place | postcode | 12345 | country:de | - When importing - Then placex has no entry for N3 - When updating places - | osm | class | type | postcode | housenr | geometry | - | N3 | place | house | 12345 | 13 | country:de | - Then placex contains - | object | class | type | - | N3 | place | house | - - Scenario: remove boundary when changing from polygon to way - Given the grid - | 1 | 2 | - | 3 | 4 | - And the places - | osm | class | type | name | admin | geometry | - | W1 | boundary | administrative | Haha | 5 | (1, 2, 4, 3, 1) | - When importing - Then placex contains - | object | - | W1 | - When updating places - | osm | class | type | name | admin | geometry | - | W1 | boundary | administrative | Haha | 5 | 1, 2, 4, 3 | - Then placex has no entry for W1 - - #895 - Scenario: update rank when boundary is downgraded from admin to historic - Given the grid - | 1 | 2 | - | 3 | 4 | - And the places - | osm | class | type | name | admin | geometry | - | W1 | boundary | administrative | Haha | 5 | (1, 2, 4, 3, 1) | - When importing - Then placex contains - | object | rank_address | - | W1 | 10 | - When updating places - | osm | class | type | name | admin | geometry | - | W1 | boundary | historic | Haha | 5 | (1, 2, 4, 3, 1) | - Then placex contains - | object | rank_address | - | W1 | 0 | diff --git a/test/bdd/environment.py b/test/bdd/environment.py deleted file mode 100644 index bedbe8d2..00000000 --- a/test/bdd/environment.py +++ /dev/null @@ -1,64 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later -# -# This file is part of Nominatim. (https://nominatim.org) -# -# Copyright (C) 2025 by the Nominatim developer community. -# For a full list of authors see the git log. -from pathlib import Path -import sys - -from behave import * # noqa - -sys.path.insert(1, str(Path(__file__, '..', '..', '..', 'src').resolve())) - -from steps.geometry_factory import GeometryFactory # noqa: E402 -from steps.nominatim_environment import NominatimEnvironment # noqa: E402 - -TEST_BASE_DIR = Path(__file__, '..', '..').resolve() - -userconfig = { - 'REMOVE_TEMPLATE': False, - 'KEEP_TEST_DB': False, - 'DB_HOST': None, - 'DB_PORT': None, - 'DB_USER': None, - 'DB_PASS': None, - 'TEMPLATE_DB': 'test_template_nominatim', - 'TEST_DB': 'test_nominatim', - 'API_TEST_DB': 'test_api_nominatim', - 'API_TEST_FILE': TEST_BASE_DIR / 'testdb' / 'apidb-test-data.pbf', - 'TOKENIZER': None, # Test with a custom tokenizer - 'STYLE': 'extratags', - 'API_ENGINE': 'falcon' -} - - -use_step_matcher("re") # noqa: F405 - - -def before_all(context): - # logging setup - context.config.setup_logging() - # set up -D options - for k, v in userconfig.items(): - context.config.userdata.setdefault(k, v) - # Nominatim test setup - context.nominatim = NominatimEnvironment(context.config.userdata) - context.osm = GeometryFactory() - - -def before_scenario(context, scenario): - if 'SQLITE' not in context.tags \ - and context.config.userdata['API_TEST_DB'].startswith('sqlite:'): - context.scenario.skip("Not usable with Sqlite database.") - elif 'DB' in context.tags: - context.nominatim.setup_db(context) - elif 'APIDB' in context.tags: - context.nominatim.setup_api_db() - elif 'UNKNOWNDB' in context.tags: - context.nominatim.setup_unknown_db() - - -def after_scenario(context, scenario): - if 'DB' in context.tags: - context.nominatim.teardown_db(context) diff --git a/test/bdd/steps/check_functions.py b/test/bdd/steps/check_functions.py deleted file mode 100644 index df9e6f35..00000000 --- a/test/bdd/steps/check_functions.py +++ /dev/null @@ -1,99 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# This file is part of Nominatim. (https://nominatim.org) -# -# Copyright (C) 2025 by the Nominatim developer community. -# For a full list of authors see the git log. -""" -Collection of assertion functions used for the steps. -""" -import json -import math -import re - - -OSM_TYPE = {'N': 'node', 'W': 'way', 'R': 'relation', - 'n': 'node', 'w': 'way', 'r': 'relation', - 'node': 'n', 'way': 'w', 'relation': 'r'} - - -class OsmType: - """ Compares an OSM type, accepting both N/R/W and node/way/relation. - """ - - def __init__(self, value): - self.value = value - - def __eq__(self, other): - return other == self.value or other == OSM_TYPE[self.value] - - def __str__(self): - return f"{self.value} or {OSM_TYPE[self.value]}" - - -class Field: - """ Generic comparator for fields, which looks at the type of the - value compared. - """ - def __init__(self, value, **extra_args): - self.value = value - self.extra_args = extra_args - - def __eq__(self, other): - if isinstance(self.value, float): - return math.isclose(self.value, float(other), **self.extra_args) - - if self.value.startswith('^'): - return re.fullmatch(self.value, str(other)) - - if isinstance(other, dict): - return other == eval('{' + self.value + '}') - - return str(self.value) == str(other) - - def __str__(self): - return str(self.value) - - -class Bbox: - """ Comparator for bounding boxes. - """ - def __init__(self, bbox_string): - self.coord = [float(x) for x in bbox_string.split(',')] - - def __contains__(self, item): - if isinstance(item, str): - item = item.split(',') - item = list(map(float, item)) - - if len(item) == 2: - return self.coord[0] <= item[0] <= self.coord[2] \ - and self.coord[1] <= item[1] <= self.coord[3] - - if len(item) == 4: - return item[0] >= self.coord[0] and item[1] <= self.coord[1] \ - and item[2] >= self.coord[2] and item[3] <= self.coord[3] - - raise ValueError("Not a coordinate or bbox.") - - def __str__(self): - return str(self.coord) - - -def check_for_attributes(obj, attrs, presence='present'): - """ Check that the object has the given attributes. 'attrs' is a - string with a comma-separated list of attributes. If 'presence' - is set to 'absent' then the function checks that the attributes do - not exist for the object - """ - def _dump_json(): - return json.dumps(obj, sort_keys=True, indent=2, ensure_ascii=False) - - for attr in attrs.split(','): - attr = attr.strip() - if presence == 'absent': - assert attr not in obj, \ - f"Unexpected attribute {attr}. Full response:\n{_dump_json()}" - else: - assert attr in obj, \ - f"No attribute '{attr}'. Full response:\n{_dump_json()}" diff --git a/test/bdd/steps/geometry_alias.py b/test/bdd/steps/geometry_alias.py deleted file mode 100644 index dbec5201..00000000 --- a/test/bdd/steps/geometry_alias.py +++ /dev/null @@ -1,262 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# This file is part of Nominatim. (https://nominatim.org) -# -# Copyright (C) 2025 by the Nominatim developer community. -# For a full list of authors see the git log. -""" -Collection of aliases for various world coordinates. -""" - -ALIASES = { - # Country aliases - 'AD': (1.58972, 42.54241), - 'AE': (54.61589, 24.82431), - 'AF': (65.90264, 34.84708), - 'AG': (-61.72430, 17.069), - 'AI': (-63.10571, 18.25461), - 'AL': (19.84941, 40.21232), - 'AM': (44.64229, 40.37821), - 'AO': (16.21924, -12.77014), - 'AQ': (44.99999, -75.65695), - 'AR': (-61.10759, -34.37615), - 'AS': (-170.68470, -14.29307), - 'AT': (14.25747, 47.36542), - 'AU': (138.23155, -23.72068), - 'AW': (-69.98255, 12.555), - 'AX': (19.91839, 59.81682), - 'AZ': (48.38555, 40.61639), - 'BA': (17.18514, 44.25582), - 'BB': (-59.53342, 13.19), - 'BD': (89.75989, 24.34205), - 'BE': (4.90078, 50.34682), - 'BF': (-0.56743, 11.90471), - 'BG': (24.80616, 43.09859), - 'BH': (50.52032, 25.94685), - 'BI': (29.54561, -2.99057), - 'BJ': (2.70062, 10.02792), - 'BL': (-62.79349, 17.907), - 'BM': (-64.77406, 32.30199), - 'BN': (114.52196, 4.28638), - 'BO': (-62.02473, -17.77723), - 'BQ': (-63.14322, 17.566), - 'BR': (-45.77065, -9.58685), - 'BS': (-77.60916, 23.8745), - 'BT': (90.01350, 27.28137), - 'BV': (3.35744, -54.4215), - 'BW': (23.51505, -23.48391), - 'BY': (26.77259, 53.15885), - 'BZ': (-88.63489, 16.33951), - 'CA': (-107.74817, 67.12612), - 'CC': (96.84420, -12.01734), - 'CD': (24.09544, -1.67713), - 'CF': (22.58701, 5.98438), - 'CG': (15.78875, 0.40388), - 'CH': (7.65705, 46.57446), - 'CI': (-6.31190, 6.62783), - 'CK': (-159.77835, -21.23349), - 'CL': (-70.41790, -53.77189), - 'CM': (13.26022, 5.94519), - 'CN': (96.44285, 38.04260), - 'CO': (-72.52951, 2.45174), - 'CR': (-83.83314, 9.93514), - 'CU': (-80.81673, 21.88852), - 'CV': (-24.50810, 14.929), - 'CW': (-68.96409, 12.1845), - 'CX': (105.62411, -10.48417), - 'CY': (32.95922, 35.37010), - 'CZ': (16.32098, 49.50692), - 'DE': (9.30716, 50.21289), - 'DJ': (42.96904, 11.41542), - 'DK': (9.18490, 55.98916), - 'DM': (-61.00358, 15.65470), - 'DO': (-69.62855, 18.58841), - 'DZ': (4.24749, 25.79721), - 'EC': (-77.45831, -0.98284), - 'EE': (23.94288, 58.43952), - 'EG': (28.95293, 28.17718), - 'EH': (-13.69031, 25.01241), - 'ER': (39.01223, 14.96033), - 'ES': (-2.59110, 38.79354), - 'ET': (38.61697, 7.71399), - 'FI': (26.89798, 63.56194), - 'FJ': (177.91853, -17.74237), - 'FK': (-58.99044, -51.34509), - 'FM': (151.95358, 8.5045), - 'FO': (-6.60483, 62.10000), - 'FR': (0.28410, 47.51045), - 'GA': (10.81070, -0.07429), - 'GB': (-0.92823, 52.01618), - 'GD': (-61.64524, 12.191), - 'GE': (44.16664, 42.00385), - 'GF': (-53.46524, 3.56188), - 'GG': (-2.50580, 49.58543), - 'GH': (-0.46348, 7.16051), - 'GI': (-5.32053, 36.11066), - 'GL': (-33.85511, 74.66355), - 'GM': (-16.40960, 13.25), - 'GN': (-13.83940, 10.96291), - 'GP': (-61.68712, 16.23049), - 'GQ': (10.23973, 1.43119), - 'GR': (23.17850, 39.06206), - 'GS': (-36.49430, -54.43067), - 'GT': (-90.74368, 15.20428), - 'GU': (144.73362, 13.44413), - 'GW': (-14.83525, 11.92486), - 'GY': (-58.45167, 5.73698), - 'HK': (114.18577, 22.34923), - 'HM': (73.68230, -53.22105), - 'HN': (-86.95414, 15.23820), - 'HR': (17.49966, 45.52689), - 'HT': (-73.51925, 18.32492), - 'HU': (20.35362, 47.51721), - 'ID': (123.34505, -0.83791), - 'IE': (-9.00520, 52.87725), - 'IL': (35.46314, 32.86165), - 'IM': (-4.86740, 54.023), - 'IN': (88.67620, 27.86155), - 'IO': (71.42743, -6.14349), - 'IQ': (42.58109, 34.26103), - 'IR': (56.09355, 30.46751), - 'IS': (-17.51785, 64.71687), - 'IT': (10.42639, 44.87904), - 'JE': (-2.19261, 49.12458), - 'JM': (-76.84020, 18.3935), - 'JO': (36.55552, 30.75741), - 'JP': (138.72531, 35.92099), - 'KE': (36.90602, 1.08512), - 'KG': (76.15571, 41.66497), - 'KH': (104.31901, 12.95555), - 'KI': (173.63353, 0.139), - 'KM': (44.31474, -12.241), - 'KN': (-62.69379, 17.2555), - 'KP': (126.65575, 39.64575), - 'KR': (127.27740, 36.41388), - 'KW': (47.30684, 29.69180), - 'KY': (-81.07455, 19.29949), - 'KZ': (72.00811, 49.88855), - 'LA': (102.44391, 19.81609), - 'LB': (35.48464, 33.41766), - 'LC': (-60.97894, 13.891), - 'LI': (9.54693, 47.15934), - 'LK': (80.38520, 8.41649), - 'LR': (-11.16960, 4.04122), - 'LS': (28.66984, -29.94538), - 'LT': (24.51735, 55.49293), - 'LU': (6.08649, 49.81533), - 'LV': (23.51033, 56.67144), - 'LY': (15.36841, 28.12177), - 'MA': (-4.03061, 33.21696), - 'MC': (7.47743, 43.62917), - 'MD': (29.61725, 46.66517), - 'ME': (19.72291, 43.02441), - 'MF': (-63.06666, 18.08102), - 'MG': (45.86378, -20.50245), - 'MH': (171.94982, 5.983), - 'MK': (21.42108, 41.08980), - 'ML': (-1.93310, 16.46993), - 'MM': (95.54624, 21.09620), - 'MN': (99.81138, 48.18615), - 'MO': (113.56441, 22.16209), - 'MP': (145.21345, 14.14902), - 'MQ': (-60.81128, 14.43706), - 'MR': (-9.42324, 22.59251), - 'MS': (-62.19455, 16.745), - 'MT': (14.38363, 35.94467), - 'MU': (57.55121, -20.41), - 'MV': (73.39292, 4.19375), - 'MW': (33.95722, -12.28218), - 'MX': (-105.89221, 25.86826), - 'MY': (112.71154, 2.10098), - 'MZ': (37.58689, -13.72682), - 'NA': (16.68569, -21.46572), - 'NC': (164.95322, -20.38889), - 'NE': (10.06041, 19.08273), - 'NF': (167.95718, -29.0645), - 'NG': (10.17781, 10.17804), - 'NI': (-85.87974, 13.21715), - 'NL': (-68.57062, 12.041), - 'NO': (23.11556, 70.09934), - 'NP': (83.36259, 28.13107), - 'NR': (166.93479, -0.5275), - 'NU': (-169.84873, -19.05305), - 'NZ': (167.97209, -45.13056), - 'OM': (56.86055, 20.47413), - 'PA': (-79.40160, 8.80656), - 'PE': (-78.66540, -7.54711), - 'PF': (-145.05719, -16.70862), - 'PG': (146.64600, -7.37427), - 'PH': (121.48359, 15.09965), - 'PK': (72.11347, 31.14629), - 'PL': (17.88136, 52.77182), - 'PM': (-56.19515, 46.78324), - 'PN': (-130.10642, -25.06955), - 'PR': (-65.88755, 18.37169), - 'PS': (35.39801, 32.24773), - 'PT': (-8.45743, 40.11154), - 'PW': (134.49645, 7.3245), - 'PY': (-59.51787, -22.41281), - 'QA': (51.49903, 24.99816), - 'RE': (55.77345, -21.36388), - 'RO': (26.37632, 45.36120), - 'RS': (20.40371, 44.56413), - 'RU': (116.44060, 59.06780), - 'RW': (29.57882, -1.62404), - 'SA': (47.73169, 22.43790), - 'SB': (164.63894, -10.23606), - 'SC': (46.36566, -9.454), - 'SD': (28.14720, 14.56423), - 'SE': (15.68667, 60.35568), - 'SG': (103.84187, 1.304), - 'SH': (-12.28155, -37.11546), - 'SI': (14.04738, 46.39085), - 'SJ': (15.27552, 79.23365), - 'SK': (20.41603, 48.86970), - 'SL': (-11.47773, 8.78156), - 'SM': (12.46062, 43.94279), - 'SN': (-15.37111, 14.99477), - 'SO': (46.93383, 9.34094), - 'SR': (-55.42864, 4.56985), - 'SS': (28.13573, 8.50933), - 'ST': (6.61025, 0.2215), - 'SV': (-89.36665, 13.43072), - 'SX': (-63.15393, 17.9345), - 'SY': (38.15513, 35.34221), - 'SZ': (31.78263, -26.14244), - 'TC': (-71.32554, 21.35), - 'TD': (17.42092, 13.46223), - 'TF': (137.5, -67.5), - 'TG': (1.06983, 7.87677), - 'TH': (102.00877, 16.42310), - 'TJ': (71.91349, 39.01527), - 'TK': (-171.82603, -9.20990), - 'TL': (126.22520, -8.72636), - 'TM': (57.71603, 39.92534), - 'TN': (9.04958, 34.84199), - 'TO': (-176.99320, -23.11104), - 'TR': (32.82002, 39.86350), - 'TT': (-60.70793, 11.1385), - 'TV': (178.77499, -9.41685), - 'TW': (120.30074, 23.17002), - 'TZ': (33.53892, -5.01840), - 'UA': (33.44335, 49.30619), - 'UG': (32.96523, 2.08584), - 'UM': (-169.50993, 16.74605), - 'US': (-116.39535, 40.71379), - 'UY': (-56.46505, -33.62658), - 'UZ': (61.35529, 42.96107), - 'VA': (12.33197, 42.04931), - 'VC': (-61.09905, 13.316), - 'VE': (-64.88323, 7.69849), - 'VG': (-64.62479, 18.419), - 'VI': (-64.88950, 18.32263), - 'VN': (104.20179, 10.27644), - 'VU': (167.31919, -15.88687), - 'WF': (-176.20781, -13.28535), - 'WS': (-172.10966, -13.85093), - 'YE': (45.94562, 16.16338), - 'YT': (44.93774, -12.60882), - 'ZA': (23.19488, -30.43276), - 'ZM': (26.38618, -14.39966), - 'ZW': (30.12419, -19.86907) - } diff --git a/test/bdd/steps/geometry_factory.py b/test/bdd/steps/geometry_factory.py deleted file mode 100644 index 504227b3..00000000 --- a/test/bdd/steps/geometry_factory.py +++ /dev/null @@ -1,88 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# This file is part of Nominatim. (https://nominatim.org) -# -# Copyright (C) 2025 by the Nominatim developer community. -# For a full list of authors see the git log. -from steps.geometry_alias import ALIASES - - -class GeometryFactory: - """ Provides functions to create geometries from coordinates and data grids. - """ - - def __init__(self): - self.grid = {} - - def parse_geometry(self, geom): - """ Create a WKT SQL term for the given geometry. - The function understands the following formats: - - country: - Point geometry guaranteed to be in the given country -

- Point geometry -

,...,

- Line geometry - (

,...,

) - Polygon geometry - -

may either be a coordinate of the form ' ' or a single - number. In the latter case it must refer to a point in - a previously defined grid. - """ - if geom.startswith('country:'): - ccode = geom[8:].upper() - assert ccode in ALIASES, "Geometry error: unknown country " + ccode - return "ST_SetSRID('POINT({} {})'::geometry, 4326)".format(*ALIASES[ccode]) - - if geom.find(',') < 0: - out = "POINT({})".format(self.mk_wkt_point(geom)) - elif geom.find('(') < 0: - out = "LINESTRING({})".format(self.mk_wkt_points(geom)) - else: - out = "POLYGON(({}))".format(self.mk_wkt_points(geom.strip('() '))) - - return "ST_SetSRID('{}'::geometry, 4326)".format(out) - - def mk_wkt_point(self, point): - """ Parse a point description. - The point may either consist of 'x y' coordinates or a number - that refers to a grid setup. - """ - geom = point.strip() - if geom.find(' ') >= 0: - return geom - - try: - pt = self.grid_node(int(geom)) - except ValueError: - assert False, "Scenario error: Point '{}' is not a number".format(geom) - - assert pt is not None, "Scenario error: Point '{}' not found in grid".format(geom) - return "{} {}".format(*pt) - - def mk_wkt_points(self, geom): - """ Parse a list of points. - The list must be a comma-separated list of points. Points - in coordinate and grid format may be mixed. - """ - return ','.join([self.mk_wkt_point(x) for x in geom.split(',')]) - - def set_grid(self, lines, grid_step, origin=(0.0, 0.0)): - """ Replace the grid with one from the given lines. - """ - self.grid = {} - y = origin[1] - for line in lines: - x = origin[0] - for pt_id in line: - if pt_id.isdigit(): - self.grid[int(pt_id)] = (x, y) - x += grid_step - y += grid_step - - def grid_node(self, nodeid): - """ Get the coordinates for the given grid node. - """ - return self.grid.get(nodeid) diff --git a/test/bdd/steps/http_responses.py b/test/bdd/steps/http_responses.py deleted file mode 100644 index f803a45f..00000000 --- a/test/bdd/steps/http_responses.py +++ /dev/null @@ -1,253 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# This file is part of Nominatim. (https://nominatim.org) -# -# Copyright (C) 2025 by the Nominatim developer community. -# For a full list of authors see the git log. -""" -Classes wrapping HTTP responses from the Nominatim API. -""" -import re -import json -import xml.etree.ElementTree as ET - -from check_functions import OsmType, Field, check_for_attributes - - -class GenericResponse: - """ Common base class for all API responses. - """ - def __init__(self, page, fmt, errorcode=200): - fmt = fmt.strip() - if fmt == 'jsonv2': - fmt = 'json' - - self.page = page - self.format = fmt - self.errorcode = errorcode - self.result = [] - self.header = dict() - - if errorcode == 200 and fmt != 'debug': - getattr(self, '_parse_' + fmt)() - - def _parse_json(self): - m = re.fullmatch(r'([\w$][^(]*)\((.*)\)', self.page) - if m is None: - code = self.page - else: - code = m.group(2) - self.header['json_func'] = m.group(1) - self.result = json.JSONDecoder().decode(code) - if isinstance(self.result, dict): - if 'error' in self.result: - self.result = [] - else: - self.result = [self.result] - - def _parse_geojson(self): - self._parse_json() - if self.result: - geojson = self.result[0] - # check for valid geojson - check_for_attributes(geojson, 'type,features') - assert geojson['type'] == 'FeatureCollection' - assert isinstance(geojson['features'], list) - - self.result = [] - for result in geojson['features']: - check_for_attributes(result, 'type,properties,geometry') - assert result['type'] == 'Feature' - new = result['properties'] - check_for_attributes(new, 'geojson', 'absent') - new['geojson'] = result['geometry'] - if 'bbox' in result: - check_for_attributes(new, 'boundingbox', 'absent') - # bbox is minlon, minlat, maxlon, maxlat - # boundingbox is minlat, maxlat, minlon, maxlon - new['boundingbox'] = [result['bbox'][1], - result['bbox'][3], - result['bbox'][0], - result['bbox'][2]] - for k, v in geojson.items(): - if k not in ('type', 'features'): - check_for_attributes(new, '__' + k, 'absent') - new['__' + k] = v - self.result.append(new) - - def _parse_geocodejson(self): - self._parse_geojson() - if self.result: - for r in self.result: - assert set(r.keys()) == {'geocoding', 'geojson', '__geocoding'}, \ - f"Unexpected keys in result: {r.keys()}" - check_for_attributes(r['geocoding'], 'geojson', 'absent') - inner = r.pop('geocoding') - r.update(inner) - - def assert_address_field(self, idx, field, value): - """ Check that result rows`idx` has a field `field` with value `value` - in its address. If idx is None, then all results are checked. - """ - if idx is None: - todo = range(len(self.result)) - else: - todo = [int(idx)] - - for idx in todo: - self.check_row(idx, 'address' in self.result[idx], "No field 'address'") - - address = self.result[idx]['address'] - self.check_row_field(idx, field, value, base=address) - - def match_row(self, row, context=None, field=None): - """ Match the result fields against the given behave table row. - """ - if 'ID' in row.headings: - todo = [int(row['ID'])] - else: - todo = range(len(self.result)) - - for i in todo: - subdict = self.result[i] - if field is not None: - for key in field.split('.'): - self.check_row(i, key in subdict, f"Missing subfield {key}") - subdict = subdict[key] - self.check_row(i, isinstance(subdict, dict), - f"Subfield {key} not a dict") - - for name, value in zip(row.headings, row.cells): - if name == 'ID': - pass - elif name == 'osm': - self.check_row_field(i, 'osm_type', OsmType(value[0]), base=subdict) - self.check_row_field(i, 'osm_id', Field(value[1:]), base=subdict) - elif name == 'centroid': - if ' ' in value: - lon, lat = value.split(' ') - elif context is not None: - lon, lat = context.osm.grid_node(int(value)) - else: - raise RuntimeError("Context needed when using grid coordinates") - self.check_row_field(i, 'lat', Field(float(lat), abs_tol=1e-07), base=subdict) - self.check_row_field(i, 'lon', Field(float(lon), abs_tol=1e-07), base=subdict) - else: - self.check_row_field(i, name, Field(value), base=subdict) - - def check_row(self, idx, check, msg): - """ Assert for the condition 'check' and print 'msg' on fail together - with the contents of the failing result. - """ - class _RowError: - def __init__(self, row): - self.row = row - - def __str__(self): - return f"{msg}. Full row {idx}:\n" \ - + json.dumps(self.row, indent=4, ensure_ascii=False) - - assert check, _RowError(self.result[idx]) - - def check_row_field(self, idx, field, expected, base=None): - """ Check field 'field' of result 'idx' for the expected value - and print a meaningful error if the condition fails. - When 'base' is set to a dictionary, then the field is checked - in that base. The error message will still report the contents - of the full result. - """ - if base is None: - base = self.result[idx] - - self.check_row(idx, field in base, f"No field '{field}'") - value = base[field] - - self.check_row(idx, expected == value, - f"\nBad value for field '{field}'. Expected: {expected}, got: {value}") - - -class SearchResponse(GenericResponse): - """ Specialised class for search and lookup responses. - Transforms the xml response in a format similar to json. - """ - - def _parse_xml(self): - xml_tree = ET.fromstring(self.page) - - self.header = dict(xml_tree.attrib) - - for child in xml_tree: - assert child.tag == "place" - self.result.append(dict(child.attrib)) - - address = {} - for sub in child: - if sub.tag == 'extratags': - self.result[-1]['extratags'] = {} - for tag in sub: - self.result[-1]['extratags'][tag.attrib['key']] = tag.attrib['value'] - elif sub.tag == 'namedetails': - self.result[-1]['namedetails'] = {} - for tag in sub: - self.result[-1]['namedetails'][tag.attrib['desc']] = tag.text - elif sub.tag == 'geokml': - self.result[-1][sub.tag] = True - else: - address[sub.tag] = sub.text - - if address: - self.result[-1]['address'] = address - - -class ReverseResponse(GenericResponse): - """ Specialised class for reverse responses. - Transforms the xml response in a format similar to json. - """ - - def _parse_xml(self): - xml_tree = ET.fromstring(self.page) - - self.header = dict(xml_tree.attrib) - self.result = [] - - for child in xml_tree: - if child.tag == 'result': - assert not self.result, "More than one result in reverse result" - self.result.append(dict(child.attrib)) - check_for_attributes(self.result[0], 'display_name', 'absent') - self.result[0]['display_name'] = child.text - elif child.tag == 'addressparts': - assert 'address' not in self.result[0], "More than one address in result" - address = {} - for sub in child: - assert len(sub) == 0, f"Address element '{sub.tag}' has subelements" - address[sub.tag] = sub.text - self.result[0]['address'] = address - elif child.tag == 'extratags': - assert 'extratags' not in self.result[0], "More than one extratags in result" - self.result[0]['extratags'] = {} - for tag in child: - assert len(tag) == 0, f"Extratags element '{tag.attrib['key']}' has subelements" - self.result[0]['extratags'][tag.attrib['key']] = tag.attrib['value'] - elif child.tag == 'namedetails': - assert 'namedetails' not in self.result[0], "More than one namedetails in result" - self.result[0]['namedetails'] = {} - for tag in child: - assert len(tag) == 0, \ - f"Namedetails element '{tag.attrib['desc']}' has subelements" - self.result[0]['namedetails'][tag.attrib['desc']] = tag.text - elif child.tag == 'geokml': - assert 'geokml' not in self.result[0], "More than one geokml in result" - self.result[0]['geokml'] = ET.tostring(child, encoding='unicode') - else: - assert child.tag == 'error', \ - f"Unknown XML tag {child.tag} on page: {self.page}" - - -class StatusResponse(GenericResponse): - """ Specialised class for status responses. - Can also parse text responses. - """ - - def _parse_text(self): - pass diff --git a/test/bdd/steps/nominatim_environment.py b/test/bdd/steps/nominatim_environment.py deleted file mode 100644 index 22908480..00000000 --- a/test/bdd/steps/nominatim_environment.py +++ /dev/null @@ -1,315 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later -# -# This file is part of Nominatim. (https://nominatim.org) -# -# Copyright (C) 2025 by the Nominatim developer community. -# For a full list of authors see the git log. -from pathlib import Path -import tempfile - -import psycopg -from psycopg import sql as pysql - -from nominatim_db import cli -from nominatim_db.config import Configuration -from nominatim_db.db.connection import register_hstore, execute_scalar -from nominatim_db.tokenizer import factory as tokenizer_factory - - -class NominatimEnvironment: - """ Collects all functions for the execution of Nominatim functions. - """ - - def __init__(self, config): - self.src_dir = (Path(__file__) / '..' / '..' / '..' / '..').resolve() - self.db_host = config['DB_HOST'] - self.db_port = config['DB_PORT'] - self.db_user = config['DB_USER'] - self.db_pass = config['DB_PASS'] - self.template_db = config['TEMPLATE_DB'] - self.test_db = config['TEST_DB'] - self.api_test_db = config['API_TEST_DB'] - self.api_test_file = config['API_TEST_FILE'] - self.tokenizer = config['TOKENIZER'] - self.import_style = config['STYLE'] - self.reuse_template = not config['REMOVE_TEMPLATE'] - self.keep_scenario_db = config['KEEP_TEST_DB'] - - self.default_config = Configuration(None).get_os_env() - self.test_env = None - self.template_db_done = False - self.api_db_done = False - self.website_dir = None - - if not hasattr(self, f"create_api_request_func_{config['API_ENGINE']}"): - raise RuntimeError(f"Unknown API engine '{config['API_ENGINE']}'") - self.api_engine = getattr(self, f"create_api_request_func_{config['API_ENGINE']}")() - - def connect_database(self, dbname): - """ Return a connection to the database with the given name. - Uses configured host, user and port. - """ - dbargs = {'dbname': dbname, 'row_factory': psycopg.rows.dict_row} - if self.db_host: - dbargs['host'] = self.db_host - if self.db_port: - dbargs['port'] = self.db_port - if self.db_user: - dbargs['user'] = self.db_user - if self.db_pass: - dbargs['password'] = self.db_pass - return psycopg.connect(**dbargs) - - def write_nominatim_config(self, dbname): - """ Set up a custom test configuration that connects to the given - database. This sets up the environment variables so that they can - be picked up by dotenv and creates a project directory with the - appropriate website scripts. - """ - if dbname.startswith('sqlite:'): - dsn = 'sqlite:dbname={}'.format(dbname[7:]) - else: - dsn = 'pgsql:dbname={}'.format(dbname) - if self.db_host: - dsn += ';host=' + self.db_host - if self.db_port: - dsn += ';port=' + self.db_port - if self.db_user: - dsn += ';user=' + self.db_user - if self.db_pass: - dsn += ';password=' + self.db_pass - - self.test_env = dict(self.default_config) - self.test_env['NOMINATIM_DATABASE_DSN'] = dsn - self.test_env['NOMINATIM_LANGUAGES'] = 'en,de,fr,ja' - self.test_env['NOMINATIM_FLATNODE_FILE'] = '' - self.test_env['NOMINATIM_IMPORT_STYLE'] = 'full' - self.test_env['NOMINATIM_USE_US_TIGER_DATA'] = 'yes' - self.test_env['NOMINATIM_DATADIR'] = str((self.src_dir / 'data').resolve()) - self.test_env['NOMINATIM_SQLDIR'] = str((self.src_dir / 'lib-sql').resolve()) - self.test_env['NOMINATIM_CONFIGDIR'] = str((self.src_dir / 'settings').resolve()) - if self.tokenizer is not None: - self.test_env['NOMINATIM_TOKENIZER'] = self.tokenizer - if self.import_style is not None: - self.test_env['NOMINATIM_IMPORT_STYLE'] = self.import_style - - if self.website_dir is not None: - self.website_dir.cleanup() - - self.website_dir = tempfile.TemporaryDirectory() - - def get_test_config(self): - cfg = Configuration(Path(self.website_dir.name), environ=self.test_env) - return cfg - - def get_libpq_dsn(self): - dsn = self.test_env['NOMINATIM_DATABASE_DSN'] - - def quote_param(param): - key, val = param.split('=') - val = val.replace('\\', '\\\\').replace("'", "\\'") - if ' ' in val: - val = "'" + val + "'" - return key + '=' + val - - if dsn.startswith('pgsql:'): - # Old PHP DSN format. Convert before returning. - return ' '.join([quote_param(p) for p in dsn[6:].split(';')]) - - return dsn - - def db_drop_database(self, name): - """ Drop the database with the given name. - """ - with self.connect_database('postgres') as conn: - conn.autocommit = True - conn.execute(pysql.SQL('DROP DATABASE IF EXISTS') - + pysql.Identifier(name)) - - def setup_template_db(self): - """ Setup a template database that already contains common test data. - Having a template database speeds up tests considerably but at - the price that the tests sometimes run with stale data. - """ - if self.template_db_done: - return - - self.template_db_done = True - - self.write_nominatim_config(self.template_db) - - if not self._reuse_or_drop_db(self.template_db): - try: - # execute nominatim import on an empty file to get the right tables - with tempfile.NamedTemporaryFile(dir='/tmp', suffix='.xml') as fd: - fd.write(b'') - fd.flush() - self.run_nominatim('import', '--osm-file', fd.name, - '--osm2pgsql-cache', '1', - '--ignore-errors', - '--offline', '--index-noanalyse') - except: # noqa: E722 - self.db_drop_database(self.template_db) - raise - - self.run_nominatim('refresh', '--functions') - - def setup_api_db(self): - """ Setup a test against the API test database. - """ - self.write_nominatim_config(self.api_test_db) - - if self.api_test_db.startswith('sqlite:'): - return - - if not self.api_db_done: - self.api_db_done = True - - if not self._reuse_or_drop_db(self.api_test_db): - testdata = (Path(__file__) / '..' / '..' / '..' / 'testdb').resolve() - self.test_env['NOMINATIM_WIKIPEDIA_DATA_PATH'] = str(testdata) - simp_file = Path(self.website_dir.name) / 'secondary_importance.sql.gz' - simp_file.symlink_to(testdata / 'secondary_importance.sql.gz') - - try: - self.run_nominatim('import', '--osm-file', str(self.api_test_file)) - self.run_nominatim('add-data', '--tiger-data', str(testdata / 'tiger')) - self.run_nominatim('freeze') - - csv_path = str(testdata / 'full_en_phrases_test.csv') - self.run_nominatim('special-phrases', '--import-from-csv', csv_path) - except: # noqa: E722 - self.db_drop_database(self.api_test_db) - raise - - tokenizer_factory.get_tokenizer_for_db(self.get_test_config()) - - def setup_unknown_db(self): - """ Setup a test against a non-existing database. - """ - # The tokenizer needs an existing database to function. - # So start with the usual database - class _Context: - db = None - - context = _Context() - self.setup_db(context) - tokenizer_factory.create_tokenizer(self.get_test_config(), init_db=False) - - # Then drop the DB again - self.teardown_db(context, force_drop=True) - - def setup_db(self, context): - """ Setup a test against a fresh, empty test database. - """ - self.setup_template_db() - with self.connect_database(self.template_db) as conn: - conn.autocommit = True - conn.execute(pysql.SQL('DROP DATABASE IF EXISTS') - + pysql.Identifier(self.test_db)) - conn.execute(pysql.SQL('CREATE DATABASE {} TEMPLATE = {}').format( - pysql.Identifier(self.test_db), - pysql.Identifier(self.template_db))) - - self.write_nominatim_config(self.test_db) - context.db = self.connect_database(self.test_db) - context.db.autocommit = True - register_hstore(context.db) - - def teardown_db(self, context, force_drop=False): - """ Remove the test database, if it exists. - """ - if hasattr(context, 'db'): - context.db.close() - - if force_drop or not self.keep_scenario_db: - self.db_drop_database(self.test_db) - - def _reuse_or_drop_db(self, name): - """ Check for the existence of the given DB. If reuse is enabled, - then the function checks for existnce and returns True if the - database is already there. Otherwise an existing database is - dropped and always false returned. - """ - if self.reuse_template: - with self.connect_database('postgres') as conn: - num = execute_scalar(conn, - 'select count(*) from pg_database where datname = %s', - (name,)) - if num == 1: - return True - else: - self.db_drop_database(name) - - return False - - def reindex_placex(self, db): - """ Run the indexing step until all data in the placex has - been processed. Indexing during updates can produce more data - to index under some circumstances. That is why indexing may have - to be run multiple times. - """ - self.run_nominatim('index') - - def run_nominatim(self, *cmdline): - """ Run the nominatim command-line tool via the library. - """ - if self.website_dir is not None: - cmdline = list(cmdline) + ['--project-dir', self.website_dir.name] - - cli.nominatim(cli_args=cmdline, - environ=self.test_env) - - def copy_from_place(self, db): - """ Copy data from place to the placex and location_property_osmline - tables invoking the appropriate triggers. - """ - self.run_nominatim('refresh', '--functions', '--no-diff-updates') - - with db.cursor() as cur: - cur.execute("""INSERT INTO placex (osm_type, osm_id, class, type, - name, admin_level, address, - extratags, geometry) - SELECT osm_type, osm_id, class, type, - name, admin_level, address, - extratags, geometry - FROM place - WHERE not (class='place' and type='houses' and osm_type='W')""") - cur.execute("""INSERT INTO location_property_osmline (osm_id, address, linegeo) - SELECT osm_id, address, geometry - FROM place - WHERE class='place' and type='houses' - and osm_type='W' - and ST_GeometryType(geometry) = 'ST_LineString'""") - - def create_api_request_func_starlette(self): - import nominatim_api.server.starlette.server - from asgi_lifespan import LifespanManager - import httpx - - async def _request(endpoint, params, project_dir, environ, http_headers): - app = nominatim_api.server.starlette.server.get_application(project_dir, environ) - - async with LifespanManager(app): - async with httpx.AsyncClient(app=app, base_url="http://nominatim.test") as client: - response = await client.get(f"/{endpoint}", params=params, - headers=http_headers) - - return response.text, response.status_code - - return _request - - def create_api_request_func_falcon(self): - import nominatim_api.server.falcon.server - import falcon.testing - - async def _request(endpoint, params, project_dir, environ, http_headers): - app = nominatim_api.server.falcon.server.get_application(project_dir, environ) - - async with falcon.testing.ASGIConductor(app) as conductor: - response = await conductor.get(f"/{endpoint}", params=params, - headers=http_headers) - - return response.text, response.status_code - - return _request diff --git a/test/bdd/steps/place_inserter.py b/test/bdd/steps/place_inserter.py deleted file mode 100644 index dcd2baec..00000000 --- a/test/bdd/steps/place_inserter.py +++ /dev/null @@ -1,120 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# This file is part of Nominatim. (https://nominatim.org) -# -# Copyright (C) 2025 by the Nominatim developer community. -# For a full list of authors see the git log. -""" -Helper classes for filling the place table. -""" -import random -import string - - -class PlaceColumn: - """ Helper class to collect contents from a behave table row and - insert it into the place table. - """ - def __init__(self, context): - self.columns = {'admin_level': 15} - self.context = context - self.geometry = None - - def add_row(self, row, force_name): - """ Parse the content from the given behave row as place column data. - """ - for name, value in zip(row.headings, row.cells): - self._add(name, value) - - assert 'osm_type' in self.columns, "osm column missing" - - if force_name and 'name' not in self.columns: - self._add_hstore( - 'name', - 'name', - ''.join(random.choices(string.printable, k=random.randrange(30))), - ) - - return self - - def _add(self, key, value): - if hasattr(self, '_set_key_' + key): - getattr(self, '_set_key_' + key)(value) - elif key.startswith('name+'): - self._add_hstore('name', key[5:], value) - elif key.startswith('extra+'): - self._add_hstore('extratags', key[6:], value) - elif key.startswith('addr+'): - self._add_hstore('address', key[5:], value) - elif key in ('name', 'address', 'extratags'): - self.columns[key] = eval('{' + value + '}') - else: - assert key in ('class', 'type'), "Unknown column '{}'.".format(key) - self.columns[key] = None if value == '' else value - - def _set_key_name(self, value): - self._add_hstore('name', 'name', value) - - def _set_key_osm(self, value): - assert value[0] in 'NRW' and value[1:].isdigit(), \ - "OSM id needs to be of format ." - - self.columns['osm_type'] = value[0] - self.columns['osm_id'] = int(value[1:]) - - def _set_key_admin(self, value): - self.columns['admin_level'] = int(value) - - def _set_key_housenr(self, value): - if value: - self._add_hstore('address', 'housenumber', value) - - def _set_key_postcode(self, value): - if value: - self._add_hstore('address', 'postcode', value) - - def _set_key_street(self, value): - if value: - self._add_hstore('address', 'street', value) - - def _set_key_addr_place(self, value): - if value: - self._add_hstore('address', 'place', value) - - def _set_key_country(self, value): - if value: - self._add_hstore('address', 'country', value) - - def _set_key_geometry(self, value): - self.geometry = self.context.osm.parse_geometry(value) - assert self.geometry is not None, "Bad geometry: {}".format(value) - - def _add_hstore(self, column, key, value): - if column in self.columns: - self.columns[column][key] = value - else: - self.columns[column] = {key: value} - - def db_delete(self, cursor): - """ Issue a delete for the given OSM object. - """ - cursor.execute('DELETE FROM place WHERE osm_type = %s and osm_id = %s', - (self.columns['osm_type'], self.columns['osm_id'])) - - def db_insert(self, cursor): - """ Insert the collected data into the database. - """ - if self.columns['osm_type'] == 'N' and self.geometry is None: - pt = self.context.osm.grid_node(self.columns['osm_id']) - if pt is None: - pt = (random.uniform(-180, 180), random.uniform(-90, 90)) - - self.geometry = "ST_SetSRID(ST_Point(%f, %f), 4326)" % pt - else: - assert self.geometry is not None, "Geometry missing" - - query = 'INSERT INTO place ({}, geometry) values({}, {})'.format( - ','.join(self.columns.keys()), - ','.join(['%s' for x in range(len(self.columns))]), - self.geometry) - cursor.execute(query, list(self.columns.values())) diff --git a/test/bdd/steps/steps_api_queries.py b/test/bdd/steps/steps_api_queries.py deleted file mode 100644 index de38549e..00000000 --- a/test/bdd/steps/steps_api_queries.py +++ /dev/null @@ -1,307 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later -# -# This file is part of Nominatim. (https://nominatim.org) -# -# Copyright (C) 2025 by the Nominatim developer community. -# For a full list of authors see the git log. -""" Steps that run queries against the API. -""" -from pathlib import Path -import re -import logging -import asyncio -import xml.etree.ElementTree as ET - -from http_responses import GenericResponse, SearchResponse, ReverseResponse, StatusResponse -from check_functions import Bbox, check_for_attributes -from table_compare import NominatimID - -LOG = logging.getLogger(__name__) - - -def make_todo_list(context, result_id): - if result_id is None: - context.execute_steps("then at least 1 result is returned") - return range(len(context.response.result)) - - context.execute_steps(f"then more than {result_id}results are returned") - return (int(result_id.strip()), ) - - -def compare(operator, op1, op2): - if operator == 'less than': - return op1 < op2 - elif operator == 'more than': - return op1 > op2 - elif operator == 'exactly': - return op1 == op2 - elif operator == 'at least': - return op1 >= op2 - elif operator == 'at most': - return op1 <= op2 - else: - raise ValueError(f"Unknown operator '{operator}'") - - -def send_api_query(endpoint, params, fmt, context): - if fmt is not None: - if fmt.strip() == 'debug': - params['debug'] = '1' - else: - params['format'] = fmt.strip() - - if context.table: - if context.table.headings[0] == 'param': - for line in context.table: - params[line['param']] = line['value'] - else: - for h in context.table.headings: - params[h] = context.table[0][h] - - return asyncio.run(context.nominatim.api_engine(endpoint, params, - Path(context.nominatim.website_dir.name), - context.nominatim.test_env, - getattr(context, 'http_headers', {}))) - - -@given('the HTTP header') -def add_http_header(context): - if not hasattr(context, 'http_headers'): - context.http_headers = {} - - for h in context.table.headings: - context.http_headers[h] = context.table[0][h] - - -@when(r'sending (?P\S+ )?search query "(?P.*)"(?P with address)?') -def website_search_request(context, fmt, query, addr): - params = {} - if query: - params['q'] = query - if addr is not None: - params['addressdetails'] = '1' - - outp, status = send_api_query('search', params, fmt, context) - - context.response = SearchResponse(outp, fmt or 'json', status) - - -@when(r'sending v1/reverse at (?P[\d.-]*),(?P[\d.-]*)(?: with format (?P.+))?') -def api_endpoint_v1_reverse(context, lat, lon, fmt): - params = {} - if lat is not None: - params['lat'] = lat - if lon is not None: - params['lon'] = lon - if fmt is None: - fmt = 'jsonv2' - elif fmt == "''": - fmt = None - - outp, status = send_api_query('reverse', params, fmt, context) - context.response = ReverseResponse(outp, fmt or 'xml', status) - - -@when(r'sending v1/reverse N(?P\d+)(?: with format (?P.+))?') -def api_endpoint_v1_reverse_from_node(context, nodeid, fmt): - params = {} - params['lon'], params['lat'] = (f'{c:f}' for c in context.osm.grid_node(int(nodeid))) - - outp, status = send_api_query('reverse', params, fmt, context) - context.response = ReverseResponse(outp, fmt or 'xml', status) - - -@when(r'sending (?P\S+ )?details query for (?P.*)') -def website_details_request(context, fmt, query): - params = {} - if query[0] in 'NWR': - nid = NominatimID(query) - params['osmtype'] = nid.typ - params['osmid'] = nid.oid - if nid.cls: - params['class'] = nid.cls - else: - params['place_id'] = query - outp, status = send_api_query('details', params, fmt, context) - - context.response = GenericResponse(outp, fmt or 'json', status) - - -@when(r'sending (?P\S+ )?lookup query for (?P.*)') -def website_lookup_request(context, fmt, query): - params = {'osm_ids': query} - outp, status = send_api_query('lookup', params, fmt, context) - - context.response = SearchResponse(outp, fmt or 'xml', status) - - -@when(r'sending (?P\S+ )?status query') -def website_status_request(context, fmt): - params = {} - outp, status = send_api_query('status', params, fmt, context) - - context.response = StatusResponse(outp, fmt or 'text', status) - - -@step(r'(?Pless than|more than|exactly|at least|at most) ' - r'(?P\d+) results? (?:is|are) returned') -def validate_result_number(context, operator, number): - context.execute_steps("Then a HTTP 200 is returned") - numres = len(context.response.result) - assert compare(operator, numres, int(number)), \ - f"Bad number of results: expected {operator} {number}, got {numres}." - - -@then(r'a HTTP (?P\d+) is returned') -def check_http_return_status(context, status): - assert context.response.errorcode == int(status), \ - f"Return HTTP status is {context.response.errorcode}."\ - f" Full response:\n{context.response.page}" - - -@then(r'the page contents equals "(?P.+)"') -def check_page_content_equals(context, text): - assert context.response.page == text - - -@then(r'the result is valid (?P\w+)') -def step_impl(context, fmt): - context.execute_steps("Then a HTTP 200 is returned") - if fmt.strip() == 'html': - try: - tree = ET.fromstring(context.response.page) - except Exception as ex: - assert False, f"Could not parse page: {ex}\n{context.response.page}" - - assert tree.tag == 'html' - body = tree.find('./body') - assert body is not None - assert body.find('.//script') is None - else: - assert context.response.format == fmt - - -@then(r'a (?P\w+) user error is returned') -def check_page_error(context, fmt): - context.execute_steps("Then a HTTP 400 is returned") - assert context.response.format == fmt - - if fmt == 'xml': - assert re.search(r'.+', context.response.page, re.DOTALL) is not None - else: - assert re.search(r'({"error":)', context.response.page, re.DOTALL) is not None - - -@then('result header contains') -def check_header_attr(context): - context.execute_steps("Then a HTTP 200 is returned") - for line in context.table: - assert line['attr'] in context.response.header, \ - f"Field '{line['attr']}' missing in header. " \ - f"Full header:\n{context.response.header}" - value = context.response.header[line['attr']] - assert re.fullmatch(line['value'], value) is not None, \ - f"Attribute '{line['attr']}': expected: '{line['value']}', got '{value}'" - - -@then('result header has (?Pnot )?attributes (?P.*)') -def check_header_no_attr(context, neg, attrs): - check_for_attributes(context.response.header, attrs, - 'absent' if neg else 'present') - - -@then(r'results contain(?: in field (?P.*))?') -def results_contain_in_field(context, field): - context.execute_steps("then at least 1 result is returned") - - for line in context.table: - context.response.match_row(line, context=context, field=field) - - -@then(r'result (?P\d+ )?has (?Pnot )?attributes (?P.*)') -def validate_attributes(context, lid, neg, attrs): - for i in make_todo_list(context, lid): - check_for_attributes(context.response.result[i], attrs, - 'absent' if neg else 'present') - - -@then(u'result addresses contain') -def result_addresses_contain(context): - context.execute_steps("then at least 1 result is returned") - - for line in context.table: - idx = int(line['ID']) if 'ID' in line.headings else None - - for name, value in zip(line.headings, line.cells): - if name != 'ID': - context.response.assert_address_field(idx, name, value) - - -@then(r'address of result (?P\d+) has(?P no)? types (?P.*)') -def check_address_has_types(context, lid, neg, attrs): - context.execute_steps(f"then more than {lid} results are returned") - - addr_parts = context.response.result[int(lid)]['address'] - - for attr in attrs.split(','): - if neg: - assert attr not in addr_parts - else: - assert attr in addr_parts - - -@then(r'address of result (?P\d+) (?Pis|contains)') -def check_address(context, lid, complete): - context.execute_steps(f"then more than {lid} results are returned") - - lid = int(lid) - addr_parts = dict(context.response.result[lid]['address']) - - for line in context.table: - context.response.assert_address_field(lid, line['type'], line['value']) - del addr_parts[line['type']] - - if complete == 'is': - assert len(addr_parts) == 0, f"Additional address parts found: {addr_parts!s}" - - -@then(r'result (?P\d+ )?has bounding box in (?P[\d,.-]+)') -def check_bounding_box_in_area(context, lid, coords): - expected = Bbox(coords) - - for idx in make_todo_list(context, lid): - res = context.response.result[idx] - check_for_attributes(res, 'boundingbox') - context.response.check_row(idx, res['boundingbox'] in expected, - f"Bbox is not contained in {expected}") - - -@then(r'result (?P\d+ )?has centroid in (?P[\d,.-]+)') -def check_centroid_in_area(context, lid, coords): - expected = Bbox(coords) - - for idx in make_todo_list(context, lid): - res = context.response.result[idx] - check_for_attributes(res, 'lat,lon') - context.response.check_row(idx, (res['lon'], res['lat']) in expected, - f"Centroid is not inside {expected}") - - -@then('there are(?P no)? duplicates') -def check_for_duplicates(context, neg): - context.execute_steps("then at least 1 result is returned") - - resarr = set() - has_dupe = False - - for res in context.response.result: - dup = (res['osm_type'], res['class'], res['type'], res['display_name']) - if dup in resarr: - has_dupe = True - break - resarr.add(dup) - - if neg: - assert not has_dupe, f"Found duplicate for {dup}" - else: - assert has_dupe, "No duplicates found" diff --git a/test/bdd/steps/steps_db_ops.py b/test/bdd/steps/steps_db_ops.py deleted file mode 100644 index 8b62cbc6..00000000 --- a/test/bdd/steps/steps_db_ops.py +++ /dev/null @@ -1,464 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later -# -# This file is part of Nominatim. (https://nominatim.org) -# -# Copyright (C) 2025 by the Nominatim developer community. -# For a full list of authors see the git log. -from itertools import chain - -import psycopg -from psycopg import sql as pysql - -from place_inserter import PlaceColumn -from table_compare import NominatimID, DBRow - -from nominatim_db.tokenizer import factory as tokenizer_factory - - -def check_database_integrity(context): - """ Check some generic constraints on the tables. - """ - with context.db.cursor(row_factory=psycopg.rows.tuple_row) as cur: - # place_addressline should not have duplicate (place_id, address_place_id) - cur.execute("""SELECT count(*) FROM - (SELECT place_id, address_place_id, count(*) as c - FROM place_addressline GROUP BY place_id, address_place_id) x - WHERE c > 1""") - assert cur.fetchone()[0] == 0, "Duplicates found in place_addressline" - - # word table must not have empty word_tokens - cur.execute("SELECT count(*) FROM word WHERE word_token = ''") - assert cur.fetchone()[0] == 0, "Empty word tokens found in word table" - -# GIVEN ################################## - - -@given("the (?Pnamed )?places") -def add_data_to_place_table(context, named): - """ Add entries into the place table. 'named places' makes sure that - the entries get a random name when none is explicitly given. - """ - with context.db.cursor() as cur: - cur.execute('ALTER TABLE place DISABLE TRIGGER place_before_insert') - for row in context.table: - PlaceColumn(context).add_row(row, named is not None).db_insert(cur) - cur.execute('ALTER TABLE place ENABLE TRIGGER place_before_insert') - - -@given("the relations") -def add_data_to_planet_relations(context): - """ Add entries into the osm2pgsql relation middle table. This is needed - for tests on data that looks up members. - """ - with context.db.cursor() as cur: - cur.execute("SELECT value FROM osm2pgsql_properties WHERE property = 'db_format'") - row = cur.fetchone() - if row is None or row['value'] == '1': - for r in context.table: - last_node = 0 - last_way = 0 - parts = [] - if r['members']: - members = [] - for m in r['members'].split(','): - mid = NominatimID(m) - if mid.typ == 'N': - parts.insert(last_node, int(mid.oid)) - last_node += 1 - last_way += 1 - elif mid.typ == 'W': - parts.insert(last_way, int(mid.oid)) - last_way += 1 - else: - parts.append(int(mid.oid)) - - members.extend((mid.typ.lower() + mid.oid, mid.cls or '')) - else: - members = None - - tags = chain.from_iterable([(h[5:], r[h]) for h in r.headings - if h.startswith("tags+")]) - - cur.execute("""INSERT INTO planet_osm_rels (id, way_off, rel_off, - parts, members, tags) - VALUES (%s, %s, %s, %s, %s, %s)""", - (r['id'], last_node, last_way, parts, members, list(tags))) - else: - for r in context.table: - if r['members']: - members = [] - for m in r['members'].split(','): - mid = NominatimID(m) - members.append({'ref': mid.oid, 'role': mid.cls or '', 'type': mid.typ}) - else: - members = [] - - tags = {h[5:]: r[h] for h in r.headings if h.startswith("tags+")} - - cur.execute("""INSERT INTO planet_osm_rels (id, tags, members) - VALUES (%s, %s, %s)""", - (r['id'], psycopg.types.json.Json(tags), - psycopg.types.json.Json(members))) - - -@given("the ways") -def add_data_to_planet_ways(context): - """ Add entries into the osm2pgsql way middle table. This is necessary for - tests on that that looks up node ids in this table. - """ - with context.db.cursor() as cur: - cur.execute("SELECT value FROM osm2pgsql_properties WHERE property = 'db_format'") - row = cur.fetchone() - json_tags = row is not None and row['value'] != '1' - for r in context.table: - if json_tags: - tags = psycopg.types.json.Json({h[5:]: r[h] for h in r.headings - if h.startswith("tags+")}) - else: - tags = list(chain.from_iterable([(h[5:], r[h]) - for h in r.headings if h.startswith("tags+")])) - nodes = [int(x.strip()) for x in r['nodes'].split(',')] - - cur.execute("INSERT INTO planet_osm_ways (id, nodes, tags) VALUES (%s, %s, %s)", - (r['id'], nodes, tags)) - -# WHEN ################################## - - -@when("importing") -def import_and_index_data_from_place_table(context): - """ Import data previously set up in the place table. - """ - context.nominatim.run_nominatim('import', '--continue', 'load-data', - '--index-noanalyse', '-q', - '--offline') - - check_database_integrity(context) - - # Remove the output of the input, when all was right. Otherwise it will be - # output when there are errors that had nothing to do with the import - # itself. - context.log_capture.buffer.clear() - - -@when("updating places") -def update_place_table(context): - """ Update the place table with the given data. Also runs all triggers - related to updates and reindexes the new data. - """ - context.nominatim.run_nominatim('refresh', '--functions') - with context.db.cursor() as cur: - for row in context.table: - col = PlaceColumn(context).add_row(row, False) - col.db_delete(cur) - col.db_insert(cur) - cur.execute('SELECT flush_deleted_places()') - - context.nominatim.reindex_placex(context.db) - check_database_integrity(context) - - # Remove the output of the input, when all was right. Otherwise it will be - # output when there are errors that had nothing to do with the import - # itself. - context.log_capture.buffer.clear() - - -@when("updating postcodes") -def update_postcodes(context): - """ Rerun the calculation of postcodes. - """ - context.nominatim.run_nominatim('refresh', '--postcodes') - - -@when("marking for delete (?P.*)") -def delete_places(context, oids): - """ Remove entries from the place table. Multiple ids may be given - separated by commas. Also runs all triggers - related to updates and reindexes the new data. - """ - context.nominatim.run_nominatim('refresh', '--functions') - with context.db.cursor() as cur: - cur.execute('TRUNCATE place_to_be_deleted') - for oid in oids.split(','): - NominatimID(oid).query_osm_id(cur, 'DELETE FROM place WHERE {}') - cur.execute('SELECT flush_deleted_places()') - - context.nominatim.reindex_placex(context.db) - - # Remove the output of the input, when all was right. Otherwise it will be - # output when there are errors that had nothing to do with the import - # itself. - context.log_capture.buffer.clear() - -# THEN ################################## - - -@then("(?Pplacex|place) contains(?P exactly)?") -def check_place_contents(context, table, exact): - """ Check contents of place/placex tables. Each row represents a table row - and all data must match. Data not present in the expected table, may - be arbitrary. The rows are identified via the 'object' column which must - have an identifier of the form '[:]'. When multiple - rows match (for example because 'class' was left out and there are - multiple entries for the given OSM object) then all must match. All - expected rows are expected to be present with at least one database row. - When 'exactly' is given, there must not be additional rows in the database. - """ - with context.db.cursor() as cur: - expected_content = set() - for row in context.table: - nid = NominatimID(row['object']) - query = """SELECT *, ST_AsText(geometry) as geomtxt, - ST_GeometryType(geometry) as geometrytype """ - if table == 'placex': - query += ' ,ST_X(centroid) as cx, ST_Y(centroid) as cy' - query += " FROM %s WHERE {}" % (table, ) - nid.query_osm_id(cur, query) - assert cur.rowcount > 0, "No rows found for " + row['object'] - - for res in cur: - if exact: - expected_content.add((res['osm_type'], res['osm_id'], res['class'])) - - DBRow(nid, res, context).assert_row(row, ['object']) - - if exact: - cur.execute(pysql.SQL('SELECT osm_type, osm_id, class from') - + pysql.Identifier(table)) - actual = set([(r['osm_type'], r['osm_id'], r['class']) for r in cur]) - assert expected_content == actual, \ - f"Missing entries: {expected_content - actual}\n" \ - f"Not expected in table: {actual - expected_content}" - - -@then("(?P
placex|place) has no entry for (?P.*)") -def check_place_has_entry(context, table, oid): - """ Ensure that no database row for the given object exists. The ID - must be of the form '[:]'. - """ - with context.db.cursor() as cur: - NominatimID(oid).query_osm_id(cur, "SELECT * FROM %s where {}" % table) - assert cur.rowcount == 0, \ - "Found {} entries for ID {}".format(cur.rowcount, oid) - - -@then("search_name contains(?P not)?") -def check_search_name_contents(context, exclude): - """ Check contents of place/placex tables. Each row represents a table row - and all data must match. Data not present in the expected table, may - be arbitrary. The rows are identified via the 'object' column which must - have an identifier of the form '[:]'. All - expected rows are expected to be present with at least one database row. - """ - tokenizer = tokenizer_factory.get_tokenizer_for_db(context.nominatim.get_test_config()) - - with tokenizer.name_analyzer() as analyzer: - with context.db.cursor() as cur: - for row in context.table: - nid = NominatimID(row['object']) - nid.row_by_place_id(cur, 'search_name', - ['ST_X(centroid) as cx', 'ST_Y(centroid) as cy']) - assert cur.rowcount > 0, "No rows found for " + row['object'] - - for res in cur: - db_row = DBRow(nid, res, context) - for name, value in zip(row.headings, row.cells): - if name in ('name_vector', 'nameaddress_vector'): - items = [x.strip() for x in value.split(',')] - tokens = analyzer.get_word_token_info(items) - - if not exclude: - assert len(tokens) >= len(items), \ - f"No word entry found for {value}. Entries found: {len(tokens)}" - for word, token, wid in tokens: - if exclude: - assert wid not in res[name], \ - "Found term for {}/{}: {}".format(nid, name, wid) - else: - assert wid in res[name], \ - "Missing term for {}/{}: {}".format(nid, name, wid) - elif name != 'object': - assert db_row.contains(name, value), db_row.assert_msg(name, value) - - -@then("search_name has no entry for (?P.*)") -def check_search_name_has_entry(context, oid): - """ Check that there is noentry in the search_name table for the given - objects. IDs are in format '[:]'. - """ - with context.db.cursor() as cur: - NominatimID(oid).row_by_place_id(cur, 'search_name') - - assert cur.rowcount == 0, \ - "Found {} entries for ID {}".format(cur.rowcount, oid) - - -@then("location_postcode contains exactly") -def check_location_postcode(context): - """ Check full contents for location_postcode table. Each row represents a table row - and all data must match. Data not present in the expected table, may - be arbitrary. The rows are identified via 'country' and 'postcode' columns. - All rows must be present as excepted and there must not be additional - rows. - """ - with context.db.cursor() as cur: - cur.execute("SELECT *, ST_AsText(geometry) as geomtxt FROM location_postcode") - assert cur.rowcount == len(list(context.table)), \ - "Postcode table has {cur.rowcount} rows, expected {len(list(context.table))}." - - results = {} - for row in cur: - key = (row['country_code'], row['postcode']) - assert key not in results, "Postcode table has duplicate entry: {}".format(row) - results[key] = DBRow((row['country_code'], row['postcode']), row, context) - - for row in context.table: - db_row = results.get((row['country'], row['postcode'])) - assert db_row is not None, \ - f"Missing row for country '{row['country']}' postcode '{row['postcode']}'." - - db_row.assert_row(row, ('country', 'postcode')) - - -@then("there are(?P no)? word tokens for postcodes (?P.*)") -def check_word_table_for_postcodes(context, exclude, postcodes): - """ Check that the tokenizer produces postcode tokens for the given - postcodes. The postcodes are a comma-separated list of postcodes. - Whitespace matters. - """ - nctx = context.nominatim - tokenizer = tokenizer_factory.get_tokenizer_for_db(nctx.get_test_config()) - with tokenizer.name_analyzer() as ana: - plist = [ana.normalize_postcode(p) for p in postcodes.split(',')] - - plist.sort() - - with context.db.cursor() as cur: - cur.execute("SELECT word FROM word WHERE type = 'P' and word = any(%s)", - (plist,)) - - found = [row['word'] for row in cur] - assert len(found) == len(set(found)), f"Duplicate rows for postcodes: {found}" - - if exclude: - assert len(found) == 0, f"Unexpected postcodes: {found}" - else: - assert set(found) == set(plist), \ - f"Missing postcodes {set(plist) - set(found)}. Found: {found}" - - -@then("place_addressline contains") -def check_place_addressline(context): - """ Check the contents of the place_addressline table. Each row represents - a table row and all data must match. Data not present in the expected - table, may be arbitrary. The rows are identified via the 'object' column, - representing the addressee and the 'address' column, representing the - address item. - """ - with context.db.cursor() as cur: - for row in context.table: - nid = NominatimID(row['object']) - pid = nid.get_place_id(cur) - apid = NominatimID(row['address']).get_place_id(cur) - cur.execute(""" SELECT * FROM place_addressline - WHERE place_id = %s AND address_place_id = %s""", - (pid, apid)) - assert cur.rowcount > 0, \ - f"No rows found for place {row['object']} and address {row['address']}." - - for res in cur: - DBRow(nid, res, context).assert_row(row, ('address', 'object')) - - -@then("place_addressline doesn't contain") -def check_place_addressline_exclude(context): - """ Check that the place_addressline doesn't contain any entries for the - given addressee/address item pairs. - """ - with context.db.cursor() as cur: - for row in context.table: - pid = NominatimID(row['object']).get_place_id(cur) - apid = NominatimID(row['address']).get_place_id(cur, allow_empty=True) - if apid is not None: - cur.execute(""" SELECT * FROM place_addressline - WHERE place_id = %s AND address_place_id = %s""", - (pid, apid)) - assert cur.rowcount == 0, \ - f"Row found for place {row['object']} and address {row['address']}." - - -@then(r"W(?P\d+) expands to(?P no)? interpolation") -def check_location_property_osmline(context, oid, neg): - """ Check that the given way is present in the interpolation table. - """ - with context.db.cursor() as cur: - cur.execute("""SELECT *, ST_AsText(linegeo) as geomtxt - FROM location_property_osmline - WHERE osm_id = %s AND startnumber IS NOT NULL""", - (oid, )) - - if neg: - assert cur.rowcount == 0, "Interpolation found for way {}.".format(oid) - return - - todo = list(range(len(list(context.table)))) - for res in cur: - for i in todo: - row = context.table[i] - if (int(row['start']) == res['startnumber'] - and int(row['end']) == res['endnumber']): - todo.remove(i) - break - else: - assert False, "Unexpected row " + str(res) - - DBRow(oid, res, context).assert_row(row, ('start', 'end')) - - assert not todo, f"Unmatched lines in table: {list(context.table[i] for i in todo)}" - - -@then("location_property_osmline contains(?P exactly)?") -def check_osmline_contents(context, exact): - """ Check contents of the interpolation table. Each row represents a table row - and all data must match. Data not present in the expected table, may - be arbitrary. The rows are identified via the 'object' column which must - have an identifier of the form '[:]'. When multiple - rows match (for example because 'startnumber' was left out and there are - multiple entries for the given OSM object) then all must match. All - expected rows are expected to be present with at least one database row. - When 'exactly' is given, there must not be additional rows in the database. - """ - with context.db.cursor() as cur: - expected_content = set() - for row in context.table: - if ':' in row['object']: - nid, start = row['object'].split(':', 2) - start = int(start) - else: - nid, start = row['object'], None - - query = """SELECT *, ST_AsText(linegeo) as geomtxt, - ST_GeometryType(linegeo) as geometrytype - FROM location_property_osmline WHERE osm_id=%s""" - - if ':' in row['object']: - query += ' and startnumber = %s' - params = [int(val) for val in row['object'].split(':', 2)] - else: - params = (int(row['object']), ) - - cur.execute(query, params) - assert cur.rowcount > 0, "No rows found for " + row['object'] - - for res in cur: - if exact: - expected_content.add((res['osm_id'], res['startnumber'])) - - DBRow(nid, res, context).assert_row(row, ['object']) - - if exact: - cur.execute('SELECT osm_id, startnumber from location_property_osmline') - actual = set([(r['osm_id'], r['startnumber']) for r in cur]) - assert expected_content == actual, \ - f"Missing entries: {expected_content - actual}\n" \ - f"Not expected in table: {actual - expected_content}" diff --git a/test/bdd/steps/steps_osm_data.py b/test/bdd/steps/steps_osm_data.py deleted file mode 100644 index 69f71994..00000000 --- a/test/bdd/steps/steps_osm_data.py +++ /dev/null @@ -1,144 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later -# -# This file is part of Nominatim. (https://nominatim.org) -# -# Copyright (C) 2024 by the Nominatim developer community. -# For a full list of authors see the git log. -import tempfile -import random -import os -from pathlib import Path - -from nominatim_db.tools.exec_utils import run_osm2pgsql -from nominatim_db.tools.replication import run_osm2pgsql_updates - -from geometry_alias import ALIASES - - -def get_osm2pgsql_options(nominatim_env, fname, append): - return dict(import_file=fname, - osm2pgsql='osm2pgsql', - osm2pgsql_cache=50, - osm2pgsql_style=str(nominatim_env.get_test_config().get_import_style_file()), - osm2pgsql_style_path=nominatim_env.get_test_config().lib_dir.lua, - threads=1, - dsn=nominatim_env.get_libpq_dsn(), - flatnode_file='', - tablespaces=dict(slim_data='', slim_index='', - main_data='', main_index=''), - append=append) - - -def write_opl_file(opl, grid): - """ Create a temporary OSM file from OPL and return the file name. It is - the responsibility of the caller to delete the file again. - - Node with missing coordinates, can retrieve their coordinates from - a supplied grid. Failing that a random coordinate is assigned. - """ - with tempfile.NamedTemporaryFile(suffix='.opl', delete=False) as fd: - for line in opl.splitlines(): - if line.startswith('n') and line.find(' x') < 0: - coord = grid.grid_node(int(line[1:].split(' ')[0])) - if coord is None: - coord = (random.uniform(-180, 180), random.uniform(-90, 90)) - line += " x%f y%f" % coord - fd.write(line.encode('utf-8')) - fd.write(b'\n') - - return fd.name - - -@given('the lua style file') -def lua_style_file(context): - """ Define a custom style file to use for the import. - """ - style = Path(context.nominatim.website_dir.name) / 'custom.lua' - style.write_text(context.text) - context.nominatim.test_env['NOMINATIM_IMPORT_STYLE'] = str(style) - - -@given(u'the ([0-9.]+ )?grid(?: with origin (?P.*))?') -def define_node_grid(context, grid_step, origin): - """ - Define a grid of node positions. - Use a table to define the grid. The nodes must be integer ids. Optionally - you can give the grid distance. The default is 0.00001 degrees. - """ - if grid_step is not None: - grid_step = float(grid_step.strip()) - else: - grid_step = 0.00001 - - if origin: - if ',' in origin: - # TODO coordinate - coords = origin.split(',') - if len(coords) != 2: - raise RuntimeError('Grid origin expects origin with x,y coordinates.') - origin = (float(coords[0]), float(coords[1])) - elif origin in ALIASES: - origin = ALIASES[origin] - else: - raise RuntimeError('Grid origin must be either coordinate or alias.') - else: - origin = (0.0, 0.0) - - context.osm.set_grid([context.table.headings] + [list(h) for h in context.table], - grid_step, origin) - - -@when(u'loading osm data') -def load_osm_file(context): - """ - Load the given data into a freshly created test database using osm2pgsql. - No further indexing is done. - - The data is expected as attached text in OPL format. - """ - # create an OSM file and import it - fname = write_opl_file(context.text, context.osm) - try: - run_osm2pgsql(get_osm2pgsql_options(context.nominatim, fname, append=False)) - finally: - os.remove(fname) - - # reintroduce the triggers/indexes we've lost by having osm2pgsql set up place again - cur = context.db.cursor() - cur.execute("""CREATE TRIGGER place_before_delete BEFORE DELETE ON place - FOR EACH ROW EXECUTE PROCEDURE place_delete()""") - cur.execute("""CREATE TRIGGER place_before_insert BEFORE INSERT ON place - FOR EACH ROW EXECUTE PROCEDURE place_insert()""") - cur.execute("""CREATE UNIQUE INDEX idx_place_osm_unique ON place - USING btree(osm_id,osm_type,class,type)""") - context.db.commit() - - -@when(u'updating osm data') -def update_from_osm_file(context): - """ - Update a database previously populated with 'loading osm data'. - Needs to run indexing on the existing data first to yield the correct result. - - The data is expected as attached text in OPL format. - """ - context.nominatim.copy_from_place(context.db) - context.nominatim.run_nominatim('index') - context.nominatim.run_nominatim('refresh', '--functions') - - # create an OSM file and import it - fname = write_opl_file(context.text, context.osm) - try: - run_osm2pgsql_updates(context.db, - get_osm2pgsql_options(context.nominatim, fname, append=True)) - finally: - os.remove(fname) - - -@when('indexing') -def index_database(context): - """ - Run the Nominatim indexing step. This will process data previously - loaded with 'updating osm data' - """ - context.nominatim.run_nominatim('index') diff --git a/test/bdd/steps/table_compare.py b/test/bdd/steps/table_compare.py deleted file mode 100644 index 79c9186b..00000000 --- a/test/bdd/steps/table_compare.py +++ /dev/null @@ -1,230 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# This file is part of Nominatim. (https://nominatim.org) -# -# Copyright (C) 2025 by the Nominatim developer community. -# For a full list of authors see the git log. -""" -Functions to facilitate accessing and comparing the content of DB tables. -""" -import math -import re -import json - -import psycopg -from psycopg import sql as pysql - -ID_REGEX = re.compile(r"(?P[NRW])(?P\d+)(:(?P\w+))?") - - -class NominatimID: - """ Splits a unique identifier for places into its components. - As place_ids cannot be used for testing, we use a unique - identifier instead that is of the form [:]. - """ - - def __init__(self, oid): - self.typ = self.oid = self.cls = None - - if oid is not None: - m = ID_REGEX.fullmatch(oid) - assert m is not None, \ - "ID '{}' not of form [:]".format(oid) - - self.typ = m.group('typ') - self.oid = m.group('oid') - self.cls = m.group('cls') - - def __str__(self): - if self.cls is None: - return self.typ + self.oid - - return '{self.typ}{self.oid}:{self.cls}'.format(self=self) - - def query_osm_id(self, cur, query): - """ Run a query on cursor `cur` using osm ID, type and class. The - `query` string must contain exactly one placeholder '{}' where - the 'where' query should go. - """ - where = 'osm_type = %s and osm_id = %s' - params = [self.typ, self. oid] - - if self.cls is not None: - where += ' and class = %s' - params.append(self.cls) - - cur.execute(query.format(where), params) - - def row_by_place_id(self, cur, table, extra_columns=None): - """ Get a row by place_id from the given table using cursor `cur`. - extra_columns may contain a list additional elements for the select - part of the query. - """ - pid = self.get_place_id(cur) - query = "SELECT {} FROM {} WHERE place_id = %s".format( - ','.join(['*'] + (extra_columns or [])), table) - cur.execute(query, (pid, )) - - def get_place_id(self, cur, allow_empty=False): - """ Look up the place id for the ID. Throws an assertion if the ID - is not unique. - """ - self.query_osm_id(cur, "SELECT place_id FROM placex WHERE {}") - if cur.rowcount == 0 and allow_empty: - return None - - assert cur.rowcount == 1, \ - "Place ID {!s} not unique. Found {} entries.".format(self, cur.rowcount) - - return cur.fetchone()['place_id'] - - -class DBRow: - """ Represents a row from a database and offers comparison functions. - """ - def __init__(self, nid, db_row, context): - self.nid = nid - self.db_row = db_row - self.context = context - - def assert_row(self, row, exclude_columns): - """ Check that all columns of the given behave row are contained - in the database row. Exclude behave rows with the names given - in the `exclude_columns` list. - """ - for name, value in zip(row.headings, row.cells): - if name not in exclude_columns: - assert self.contains(name, value), self.assert_msg(name, value) - - def contains(self, name, expected): - """ Check that the DB row contains a column `name` with the given value. - """ - if '+' in name: - column, field = name.split('+', 1) - return self._contains_hstore_value(column, field, expected) - - if name == 'geometry': - return self._has_geometry(expected) - - if name not in self.db_row: - return False - - actual = self.db_row[name] - - if expected == '-': - return actual is None - - if name == 'name' and ':' not in expected: - return self._compare_column(actual[name], expected) - - if 'place_id' in name: - return self._compare_place_id(actual, expected) - - if name == 'centroid': - return self._has_centroid(expected) - - return self._compare_column(actual, expected) - - def _contains_hstore_value(self, column, field, expected): - if column == 'addr': - column = 'address' - - if column not in self.db_row: - return False - - if expected == '-': - return self.db_row[column] is None or field not in self.db_row[column] - - if self.db_row[column] is None: - return False - - return self._compare_column(self.db_row[column].get(field), expected) - - def _compare_column(self, actual, expected): - if isinstance(actual, dict): - return actual == eval('{' + expected + '}') - - return str(actual) == expected - - def _compare_place_id(self, actual, expected): - if expected == '0': - return actual == 0 - - with self.context.db.cursor() as cur: - return NominatimID(expected).get_place_id(cur) == actual - - def _has_centroid(self, expected): - if expected == 'in geometry': - with self.context.db.cursor(row_factory=psycopg.rows.tuple_row) as cur: - cur.execute("""SELECT ST_Within(ST_SetSRID(ST_Point(%(cx)s, %(cy)s), 4326), - ST_SetSRID(%(geomtxt)s::geometry, 4326))""", - (self.db_row)) - return cur.fetchone()[0] - - if ' ' in expected: - x, y = expected.split(' ') - else: - x, y = self.context.osm.grid_node(int(expected)) - - return math.isclose(float(x), self.db_row['cx']) \ - and math.isclose(float(y), self.db_row['cy']) - - def _has_geometry(self, expected): - geom = self.context.osm.parse_geometry(expected) - with self.context.db.cursor(row_factory=psycopg.rows.tuple_row) as cur: - cur.execute(pysql.SQL(""" - SELECT ST_Equals(ST_SnapToGrid({}, 0.00001, 0.00001), - ST_SnapToGrid(ST_SetSRID({}::geometry, 4326), 0.00001, 0.00001))""") - .format(pysql.SQL(geom), - pysql.Literal(self.db_row['geomtxt']))) - return cur.fetchone()[0] - - def assert_msg(self, name, value): - """ Return a string with an informative message for a failed compare. - """ - msg = "\nBad column '{}' in row '{!s}'.".format(name, self.nid) - actual = self._get_actual(name) - if actual is not None: - msg += " Expected: {}, got: {}.".format(value, actual) - else: - msg += " No such column." - - return msg + "\nFull DB row: {}".format(json.dumps(dict(self.db_row), - indent=4, default=str)) - - def _get_actual(self, name): - if '+' in name: - column, field = name.split('+', 1) - if column == 'addr': - column = 'address' - return (self.db_row.get(column) or {}).get(field) - - if name == 'geometry': - return self.db_row['geomtxt'] - - if name not in self.db_row: - return None - - if name == 'centroid': - return "POINT({cx} {cy})".format(**self.db_row) - - actual = self.db_row[name] - - if 'place_id' in name: - if actual is None: - return '' - - if actual == 0: - return "place ID 0" - - with self.context.db.cursor(row_factory=psycopg.rows.tuple_row) as cur: - cur.execute("""SELECT osm_type, osm_id, class - FROM placex WHERE place_id = %s""", - (actual, )) - - if cur.rowcount == 1: - return "{0[0]}{0[1]}:{0[2]}".format(cur.fetchone()) - - return "[place ID {} not found]".format(actual) - - return actual -- 2.39.5