From 160847e116949f516362bd50028db369717644b9 Mon Sep 17 00:00:00 2001 From: Oliver Tonnhofer Date: Tue, 5 Jun 2018 21:04:02 +0200 Subject: [PATCH] test: refactor to use go 1.7 subtests --- test/any_any_test.go | 96 ++- test/completedb_test.go | 1508 ++++++++++++++++++----------------- test/expire_tiles_test.go | 294 +++---- test/helper_test.go | 67 +- test/route_relation_test.go | 312 ++++---- test/single_table_test.go | 376 ++++----- 6 files changed, 1350 insertions(+), 1303 deletions(-) diff --git a/test/any_any_test.go b/test/any_any_test.go index 7859265..2743313 100644 --- a/test/any_any_test.go +++ b/test/any_any_test.go @@ -10,53 +10,63 @@ import ( "github.com/omniscale/imposm3/geom/geos" ) -func TestAnyAny_Prepare(t *testing.T) { - var err error +func TestAnyAny(t *testing.T) { + if testing.Short() { + t.Skip("system test skipped with -test.short") + } - ts.dir, err = ioutil.TempDir("", "imposm_test") - if err != nil { - t.Fatal(err) + ts := importTestSuite{ + name: "any_any", } - ts.config = importConfig{ - connection: "postgis://", - cacheDir: ts.dir, - osmFileName: "build/any_any.pbf", - mappingFileName: "any_any_mapping.json", - } - ts.g = geos.NewGeos() - ts.db, err = sql.Open("postgres", "sslmode=disable") - if err != nil { - t.Fatal(err) - } - ts.dropSchemas() -} + t.Run("Prepare", func(t *testing.T) { + var err error -func TestAnyAny_Import(t *testing.T) { - if ts.tableExists(t, dbschemaImport, "osm_all") != false { - t.Fatalf("table osm_all exists in schema %s", dbschemaImport) - } - ts.importOsm(t) - ts.deployOsm(t) - if ts.tableExists(t, dbschemaProduction, "osm_all") != true { - t.Fatalf("table osm_all does not exists in schema %s", dbschemaProduction) - } -} + ts.dir, err = ioutil.TempDir("", "imposm_test") + if err != nil { + t.Fatal(err) + } + ts.config = importConfig{ + connection: "postgis://", + cacheDir: ts.dir, + osmFileName: "build/any_any.pbf", + mappingFileName: "any_any_mapping.json", + } + ts.g = geos.NewGeos() -func TestAnyAny_InsertedNodes(t *testing.T) { - assertHstore(t, []checkElem{ - {"osm_all", 10000, "", nil}, // nodes without tags are not inserted - {"osm_all", 10001, "*", map[string]string{"random": "tag"}}, - {"osm_all", 10002, "*", map[string]string{"amenity": "shop"}}, - {"osm_all", 10003, "*", map[string]string{"random": "tag", "but": "mapped", "amenity": "shop"}}, - {"osm_amenities", 10002, "*", map[string]string{"amenity": "shop"}}, - {"osm_amenities", 10003, "*", map[string]string{"random": "tag", "but": "mapped", "amenity": "shop"}}, + ts.db, err = sql.Open("postgres", "sslmode=disable") + if err != nil { + t.Fatal(err) + } + ts.dropSchemas() + }) + + t.Run("Import", func(t *testing.T) { + if ts.tableExists(t, ts.dbschemaImport(), "osm_all") != false { + t.Fatalf("table osm_all exists in schema %s", ts.dbschemaImport()) + } + ts.importOsm(t) + ts.deployOsm(t) + if ts.tableExists(t, ts.dbschemaProduction(), "osm_all") != true { + t.Fatalf("table osm_all does not exists in schema %s", ts.dbschemaProduction()) + } + }) + + t.Run("InsertedNodes", func(t *testing.T) { + ts.assertHstore(t, []checkElem{ + {"osm_all", 10000, "", nil}, // nodes without tags are not inserted + {"osm_all", 10001, "*", map[string]string{"random": "tag"}}, + {"osm_all", 10002, "*", map[string]string{"amenity": "shop"}}, + {"osm_all", 10003, "*", map[string]string{"random": "tag", "but": "mapped", "amenity": "shop"}}, + {"osm_amenities", 10002, "*", map[string]string{"amenity": "shop"}}, + {"osm_amenities", 10003, "*", map[string]string{"random": "tag", "but": "mapped", "amenity": "shop"}}, + }) + }) + + t.Run("Cleanup", func(t *testing.T) { + ts.dropSchemas() + if err := os.RemoveAll(ts.dir); err != nil { + t.Error(err) + } }) } - -func TestAnyAny_Cleanup(t *testing.T) { - ts.dropSchemas() - if err := os.RemoveAll(ts.dir); err != nil { - t.Error(err) - } -} diff --git a/test/completedb_test.go b/test/completedb_test.go index 12810cd..37fd045 100644 --- a/test/completedb_test.go +++ b/test/completedb_test.go @@ -17,773 +17,781 @@ import ( "github.com/omniscale/imposm3/geom/geos" ) -var ts importTestSuite - -func TestComplete_Prepare(t *testing.T) { - var err error - - ts.dir, err = ioutil.TempDir("", "imposm_test") - if err != nil { - t.Fatal(err) - } - ts.config = importConfig{ - connection: "postgis://", - cacheDir: ts.dir, - osmFileName: "build/complete_db.pbf", - mappingFileName: "complete_db_mapping.json", - } - ts.g = geos.NewGeos() - - ts.db, err = sql.Open("postgres", "sslmode=disable") - if err != nil { - t.Fatal(err) - } - ts.dropSchemas() -} - -func TestComplete_Import(t *testing.T) { - if ts.tableExists(t, dbschemaImport, "osm_roads") != false { - t.Fatalf("table osm_roads exists in schema %s", dbschemaImport) - } - ts.importOsm(t) - if ts.tableExists(t, dbschemaImport, "osm_roads") != true { - t.Fatalf("table osm_roads does not exists in schema %s", dbschemaImport) - } -} - -func TestComplete_Deploy(t *testing.T) { - ts.deployOsm(t) - if ts.tableExists(t, dbschemaImport, "osm_roads") != false { - t.Fatalf("table osm_roads exists in schema %s", dbschemaImport) - } - if ts.tableExists(t, dbschemaProduction, "osm_roads") != true { - t.Fatalf("table osm_roads does not exists in schema %s", dbschemaProduction) - } -} - -func TestComplete_OnlyNewStyleMultipolgon(t *testing.T) { - assertRecords(t, []checkElem{ - {"osm_landusages", -1001, "wood", nil}, - {"osm_landusages", -1011, Missing, nil}, - {"osm_landusages", -1021, Missing, nil}, - }) -} - -func TestComplete_LandusageToWaterarea1(t *testing.T) { - // Parks inserted into landusages - cache := ts.cache(t) - defer cache.Close() - assertCachedWay(t, cache, 11001) - assertCachedWay(t, cache, 13001) - - assertRecords(t, []checkElem{ - {"osm_waterareas", 11001, Missing, nil}, - {"osm_waterareas", -13001, Missing, nil}, - - {"osm_waterareas_gen0", 11001, Missing, nil}, - {"osm_waterareas_gen0", -13001, Missing, nil}, - - {"osm_waterareas_gen1", 11001, Missing, nil}, - {"osm_waterareas_gen1", -13001, Missing, nil}, - - {"osm_landusages", 11001, "park", nil}, - {"osm_landusages", -13001, "park", nil}, - - {"osm_landusages_gen0", 11001, "park", nil}, - {"osm_landusages_gen0", -13001, "park", nil}, - - {"osm_landusages_gen1", 11001, "park", nil}, - {"osm_landusages_gen1", -13001, "park", nil}, - }) -} - -func TestComplete_ChangedHoleTags1(t *testing.T) { - // Multipolygon relation with untagged hole - cache := ts.cache(t) - defer cache.Close() - assertCachedWay(t, cache, 14001) - assertCachedWay(t, cache, 14011) - - assertRecords(t, []checkElem{ - {"osm_waterareas", 14011, Missing, nil}, - {"osm_waterareas", -14011, Missing, nil}, - {"osm_landusages", 14001, "park", nil}, - {"osm_landusages", -14001, Missing, nil}, - }) -} - -func TestComplete_SplitOuterMultipolygonWay1(t *testing.T) { - // Single outer way of multipolygon was inserted. - assertRecords(t, []checkElem{ - {"osm_roads", 15002, Missing, nil}, - {"osm_landusages", -15001, "park", nil}, - }) - assertGeomArea(t, checkElem{"osm_landusages", -15001, "park", nil}, 9816216452) -} - -func TestComplete_MergeOuterMultipolygonWay1(t *testing.T) { - // Splitted outer way of multipolygon was inserted. - assertRecords(t, []checkElem{ - {"osm_landusages", -16001, "park", nil}, - {"osm_roads", 16002, "residential", nil}, - }) - assertGeomArea(t, checkElem{"osm_landusages", -16001, "park", nil}, 12779350582) -} - -func TestComplete_BrokenMultipolygonWays(t *testing.T) { - // MultiPolygons with broken outer ways are handled. - // outer way does not merge (17002 has one node) - assertRecords(t, []checkElem{ - {"osm_landusages", -17001, Missing, nil}, - {"osm_roads", 17001, "residential", nil}, - {"osm_roads", 17002, Missing, nil}, - }) - - // outer way does not merge (17102 has no nodes) - assertRecords(t, []checkElem{ - {"osm_landusages", -17101, Missing, nil}, - {"osm_roads", 17101, "residential", nil}, - {"osm_roads", 17102, Missing, nil}, - }) -} - -func TestComplete_NodeWayInsertedTwice(t *testing.T) { - // Way with multiple mappings is inserted twice in same table - rows := ts.queryRows(t, "osm_roads", 18001) - if len(rows) != 2 || rows[0].osmType != "residential" || rows[1].osmType != "tram" { - t.Errorf("unexpected roads: %v", rows) - } -} - -func TestComplete_OuterWayInsertedTwice(t *testing.T) { - // Outer way with different tag value is inserted twice into same table - // behavior changed from pre-old-style-mp-removal: - // test outer way not inserted (different tag but same table) - assertRecords(t, []checkElem{ - {"osm_landusages", -19001, "farmland", nil}, - {"osm_landusages", 19002, "farmyard", nil}, - {"osm_landusages", 19001, "farm", nil}, - }) -} - -func TestComplete_OuterWayInserted(t *testing.T) { - // Outer way with different tag is inserted twice into different table - assertRecords(t, []checkElem{ - {"osm_landusages", 19101, "farm", nil}, - {"osm_landusages", 19102, "farmyard", nil}, - {"osm_admin", -19101, "administrative", nil}, - }) -} - -func TestComplete_NodeWayRefAfterDelete1(t *testing.T) { - // Nodes references way - - cache := ts.diffCache(t) - defer cache.Close() - if ids := cache.Coords.Get(20001); len(ids) != 1 || ids[0] != 20001 { - t.Error("node does not references way") - } - if ids := cache.Coords.Get(20002); len(ids) != 1 || ids[0] != 20001 { - t.Error("node does not references way") +func TestComplete(t *testing.T) { + if testing.Short() { + t.Skip("system test skipped with -test.short") } - assertRecords(t, []checkElem{ - {"osm_roads", 20001, "residential", nil}, - {"osm_barrierpoints", 20001, "block", nil}, - }) -} - -func TestComplete_WayRelRefAfterDelete1(t *testing.T) { - // Ways references relation - - cache := ts.diffCache(t) - defer cache.Close() - if ids := cache.Ways.Get(21001); len(ids) != 1 || ids[0] != 21001 { - t.Error("way does not references relation") + ts := importTestSuite{ + name: "complete", } - assertRecords(t, []checkElem{ - {"osm_roads", 21001, "residential", nil}, - {"osm_landusages", -21001, "park", nil}, - }) -} + t.Run("Prepare", func(t *testing.T) { + var err error -func TestComplete_OldStyleMpRelationWayInserted(t *testing.T) { - // Old-style-mp: Part of relation is now inserted. - assertRecords(t, []checkElem{ - {"osm_landusages", -9001, "park", map[string]string{"name": "rel 9001"}}, - {"osm_landusages", 9009, "park", map[string]string{"name": "way 9009"}}, - {"osm_landusages", -9101, "park", map[string]string{"name": "rel 9101"}}, - {"osm_landusages", 9109, "park", map[string]string{"name": "way 9109"}}, - {"osm_landusages", 9110, "scrub", nil}, - }) -} - -func TestComplete_RelationWaysInserted(t *testing.T) { - // Outer ways of multipolygon are inserted. - assertRecords(t, []checkElem{ - // no name on relation - {"osm_landusages", -9201, "park", map[string]string{"name": ""}}, - {"osm_landusages", 9201, Missing, nil}, - {"osm_landusages", 9209, Missing, nil}, - {"osm_landusages", 9210, Missing, nil}, - // outer ways of multipolygon stand for their own - {"osm_roads", 9209, "secondary", map[string]string{"name": "9209"}}, - {"osm_roads", 9210, "residential", map[string]string{"name": "9210"}}, - }) -} - -func TestComplete_RelationWayInserted(t *testing.T) { - // Part of relation was inserted twice. - assertRecords(t, []checkElem{ - {"osm_landusages", -8001, "park", map[string]string{"name": "rel 8001"}}, - {"osm_roads", 8009, "residential", nil}, - }) -} - -func TestComplete_SingleNodeWaysNotInserted(t *testing.T) { - // Ways with single/duplicate nodes are not inserted. - assertRecords(t, []checkElem{ - {"osm_landusages", 30001, Missing, nil}, - {"osm_landusages", 30002, Missing, nil}, - {"osm_landusages", 30003, Missing, nil}, - }) -} - -func TestComplete_PolygonWithDuplicateNodesIsValid(t *testing.T) { - // Polygon with duplicate nodes is valid. - assertGeomValid(t, checkElem{"osm_landusages", 30005, "park", nil}) -} - -func TestComplete_IncompletePolygons(t *testing.T) { - // Non-closed/incomplete polygons are not inserted. - - assertRecords(t, []checkElem{ - {"osm_landusages", 30004, Missing, nil}, - {"osm_landusages", 30006, Missing, nil}, - }) -} - -func TestComplete_ResidentialToSecondary(t *testing.T) { - // Residential road is not in roads_gen0/1. - - assertRecords(t, []checkElem{ - {"osm_roads", 40001, "residential", nil}, - {"osm_roads_gen0", 40001, Missing, nil}, - {"osm_roads_gen1", 40002, Missing, nil}, - }) -} - -func TestComplete_RelationBeforeRemove(t *testing.T) { - // Relation and way is inserted. - - assertRecords(t, []checkElem{ - {"osm_buildings", 50011, "yes", nil}, - {"osm_landusages", -50021, "park", nil}, - }) -} - -func TestComplete_OldStyleRelationIsIgnored(t *testing.T) { - // Relation without tags is not inserted. - - assertRecords(t, []checkElem{ - {"osm_buildings", 50111, "yes", nil}, - {"osm_buildings", -50121, Missing, nil}, - }) -} - -func TestComplete_DuplicateIds(t *testing.T) { - // Relation/way with same ID is inserted. - - assertRecords(t, []checkElem{ - {"osm_buildings", 51001, "way", nil}, - {"osm_buildings", -51001, "mp", nil}, - {"osm_buildings", 51011, "way", nil}, - {"osm_buildings", -51011, "mp", nil}, - }) -} - -func TestComplete_RelationUpdatedByNode(t *testing.T) { - // Relations was updated after modified node. - - assertGeomArea(t, checkElem{"osm_buildings", -52121, "yes", nil}, 13653930440.868315) -} - -func TestComplete_GeneralizedBananaPolygonIsValid(t *testing.T) { - // Generalized polygons are valid. - - assertGeomValid(t, checkElem{"osm_landusages", 7101, Missing, nil}) - // simplified geometies are valid too - assertGeomValid(t, checkElem{"osm_landusages_gen0", 7101, Missing, nil}) - assertGeomValid(t, checkElem{"osm_landusages_gen1", 7101, Missing, nil}) -} - -func TestComplete_GeneralizedLinestringIsValid(t *testing.T) { - // Generalized linestring is valid. - - // geometry is not simple, but valid - assertGeomLength(t, checkElem{"osm_roads", 7201, "primary", nil}, 1243660.044819) - if ts.g.IsSimple(ts.queryGeom(t, "osm_roads", 7201)) { - t.Errorf("expected non-simple geometry for 7201") - } - // check that geometry 'survives' simplification - assertGeomLength(t, checkElem{"osm_roads_gen0", 7201, "primary", nil}, 1243660.044819) - assertGeomLength(t, checkElem{"osm_roads_gen1", 7201, "primary", nil}, 1243660.044819) -} - -func TestComplete_RingWithGap(t *testing.T) { - // Multipolygon with gap (overlapping but different endpoints) gets closed - assertGeomValid(t, checkElem{"osm_landusages", -7301, Missing, nil}) - // but not way - assertRecords(t, []checkElem{ - checkElem{"osm_landusages", 7311, Missing, nil}, - }) -} - -func TestComplete_MultipolygonWithOpenRing(t *testing.T) { - // Multipolygon is inserted even if there is an open ring/member - assertGeomValid(t, checkElem{"osm_landusages", -7401, Missing, nil}) -} - -func TestComplete_UpdatedNodes1(t *testing.T) { - // Zig-Zag line is inserted. - assertGeomLength(t, checkElem{"osm_roads", 60000, Missing, nil}, 14035.61150207768) -} - -func TestComplete_UpdateNodeToCoord1(t *testing.T) { - // Node is inserted with tag. - assertRecords(t, []checkElem{ - {"osm_amenities", 70001, "police", nil}, - {"osm_amenities", 70002, Missing, nil}, - }) -} - -func TestComplete_EnumerateKey(t *testing.T) { - // Enumerate from key. - assertRecords(t, []checkElem{ - {"osm_landusages", 100001, "park", map[string]string{"enum": "1"}}, - {"osm_landusages", 100002, "park", map[string]string{"enum": "0"}}, - {"osm_landusages", 100003, "wood", map[string]string{"enum": "15"}}, - }) -} - -func TestComplete_AreaMapping(t *testing.T) { - // Mapping type dependent area-defaults. - - assertRecords(t, []checkElem{ - // highway=pedestrian - {"osm_roads", 301151, "pedestrian", nil}, - {"osm_landusages", 301151, Missing, nil}, - - // // highway=pedestrian, area=yes - {"osm_roads", 301152, Missing, nil}, - {"osm_landusages", 301152, "pedestrian", nil}, - - // // leisure=track - {"osm_roads", 301153, Missing, nil}, - {"osm_landusages", 301153, "track", nil}, - - // // leisure=track, area=no - {"osm_roads", 301154, "track", nil}, - {"osm_landusages", 301154, Missing, nil}, - }) -} - -func TestComplete_HstoreTags(t *testing.T) { - // Mapping type dependent area-defaults. - - assertHstore(t, []checkElem{ - {"osm_buildings", 401151, "*", map[string]string{"amenity": "fuel", "opening_hours": "24/7"}}, - }) -} - -// ####################################################################### - -func TestComplete_Update(t *testing.T) { - ts.updateOsm(t, "./build/complete_db.osc.gz") -} - -// ####################################################################### - -func TestComplete_NoDuplicates(t *testing.T) { - // Relations/ways are only inserted once Checks #66 - - for _, table := range []string{"osm_roads", "osm_landusages"} { - rows, err := ts.db.Query( - fmt.Sprintf(`SELECT osm_id, count(osm_id) FROM "%s"."%s" GROUP BY osm_id HAVING count(osm_id) > 1`, - dbschemaProduction, table)) + ts.dir, err = ioutil.TempDir("", "imposm_test") if err != nil { t.Fatal(err) } - var osmId, count int64 - for rows.Next() { - if err := rows.Scan(&osmId, &count); err != nil { + ts.config = importConfig{ + connection: "postgis://", + cacheDir: ts.dir, + osmFileName: "build/complete_db.pbf", + mappingFileName: "complete_db_mapping.json", + } + ts.g = geos.NewGeos() + + ts.db, err = sql.Open("postgres", "sslmode=disable") + if err != nil { + t.Fatal(err) + } + ts.dropSchemas() + }) + + t.Run("Import", func(t *testing.T) { + if ts.tableExists(t, ts.dbschemaImport(), "osm_roads") != false { + t.Fatalf("table osm_roads exists in schema %s", ts.dbschemaImport()) + } + ts.importOsm(t) + if ts.tableExists(t, ts.dbschemaImport(), "osm_roads") != true { + t.Fatalf("table osm_roads does not exists in schema %s", ts.dbschemaImport()) + } + }) + + t.Run("Deploy", func(t *testing.T) { + ts.deployOsm(t) + if ts.tableExists(t, ts.dbschemaImport(), "osm_roads") != false { + t.Fatalf("table osm_roads exists in schema %s", ts.dbschemaImport()) + } + if ts.tableExists(t, ts.dbschemaProduction(), "osm_roads") != true { + t.Fatalf("table osm_roads does not exists in schema %s", ts.dbschemaProduction()) + } + }) + + t.Run("OnlyNewStyleMultipolgon", func(t *testing.T) { + ts.assertRecords(t, []checkElem{ + {"osm_landusages", -1001, "wood", nil}, + {"osm_landusages", -1011, Missing, nil}, + {"osm_landusages", -1021, Missing, nil}, + }) + }) + + t.Run("LandusageToWaterarea1", func(t *testing.T) { + // Parks inserted into landusages + cache := ts.cache(t) + defer cache.Close() + ts.assertCachedWay(t, cache, 11001) + ts.assertCachedWay(t, cache, 13001) + + ts.assertRecords(t, []checkElem{ + {"osm_waterareas", 11001, Missing, nil}, + {"osm_waterareas", -13001, Missing, nil}, + + {"osm_waterareas_gen0", 11001, Missing, nil}, + {"osm_waterareas_gen0", -13001, Missing, nil}, + + {"osm_waterareas_gen1", 11001, Missing, nil}, + {"osm_waterareas_gen1", -13001, Missing, nil}, + + {"osm_landusages", 11001, "park", nil}, + {"osm_landusages", -13001, "park", nil}, + + {"osm_landusages_gen0", 11001, "park", nil}, + {"osm_landusages_gen0", -13001, "park", nil}, + + {"osm_landusages_gen1", 11001, "park", nil}, + {"osm_landusages_gen1", -13001, "park", nil}, + }) + }) + + t.Run("ChangedHoleTags1", func(t *testing.T) { + // Multipolygon relation with untagged hole + cache := ts.cache(t) + defer cache.Close() + ts.assertCachedWay(t, cache, 14001) + ts.assertCachedWay(t, cache, 14011) + + ts.assertRecords(t, []checkElem{ + {"osm_waterareas", 14011, Missing, nil}, + {"osm_waterareas", -14011, Missing, nil}, + {"osm_landusages", 14001, "park", nil}, + {"osm_landusages", -14001, Missing, nil}, + }) + }) + + t.Run("SplitOuterMultipolygonWay1", func(t *testing.T) { + // Single outer way of multipolygon was inserted. + ts.assertRecords(t, []checkElem{ + {"osm_roads", 15002, Missing, nil}, + {"osm_landusages", -15001, "park", nil}, + }) + ts.assertGeomArea(t, checkElem{"osm_landusages", -15001, "park", nil}, 9816216452) + }) + + t.Run("MergeOuterMultipolygonWay1", func(t *testing.T) { + // Splitted outer way of multipolygon was inserted. + ts.assertRecords(t, []checkElem{ + {"osm_landusages", -16001, "park", nil}, + {"osm_roads", 16002, "residential", nil}, + }) + ts.assertGeomArea(t, checkElem{"osm_landusages", -16001, "park", nil}, 12779350582) + }) + + t.Run("BrokenMultipolygonWays", func(t *testing.T) { + // MultiPolygons with broken outer ways are handled. + // outer way does not merge (17002 has one node) + ts.assertRecords(t, []checkElem{ + {"osm_landusages", -17001, Missing, nil}, + {"osm_roads", 17001, "residential", nil}, + {"osm_roads", 17002, Missing, nil}, + }) + + // outer way does not merge (17102 has no nodes) + ts.assertRecords(t, []checkElem{ + {"osm_landusages", -17101, Missing, nil}, + {"osm_roads", 17101, "residential", nil}, + {"osm_roads", 17102, Missing, nil}, + }) + }) + + t.Run("NodeWayInsertedTwice", func(t *testing.T) { + // Way with multiple mappings is inserted twice in same table + rows := ts.queryRows(t, "osm_roads", 18001) + if len(rows) != 2 || rows[0].osmType != "residential" || rows[1].osmType != "tram" { + t.Errorf("unexpected roads: %v", rows) + } + }) + + t.Run("OuterWayInsertedTwice", func(t *testing.T) { + // Outer way with different tag value is inserted twice into same table + // behavior changed from pre-old-style-mp-removal: + // test outer way not inserted (different tag but same table) + ts.assertRecords(t, []checkElem{ + {"osm_landusages", -19001, "farmland", nil}, + {"osm_landusages", 19002, "farmyard", nil}, + {"osm_landusages", 19001, "farm", nil}, + }) + }) + + t.Run("OuterWayInserted", func(t *testing.T) { + // Outer way with different tag is inserted twice into different table + ts.assertRecords(t, []checkElem{ + {"osm_landusages", 19101, "farm", nil}, + {"osm_landusages", 19102, "farmyard", nil}, + {"osm_admin", -19101, "administrative", nil}, + }) + }) + + t.Run("NodeWayRefAfterDelete1", func(t *testing.T) { + // Nodes references way + + cache := ts.diffCache(t) + defer cache.Close() + if ids := cache.Coords.Get(20001); len(ids) != 1 || ids[0] != 20001 { + t.Error("node does not references way") + } + if ids := cache.Coords.Get(20002); len(ids) != 1 || ids[0] != 20001 { + t.Error("node does not references way") + } + + ts.assertRecords(t, []checkElem{ + {"osm_roads", 20001, "residential", nil}, + {"osm_barrierpoints", 20001, "block", nil}, + }) + }) + + t.Run("WayRelRefAfterDelete1", func(t *testing.T) { + // Ways references relation + + cache := ts.diffCache(t) + defer cache.Close() + if ids := cache.Ways.Get(21001); len(ids) != 1 || ids[0] != 21001 { + t.Error("way does not references relation") + } + + ts.assertRecords(t, []checkElem{ + {"osm_roads", 21001, "residential", nil}, + {"osm_landusages", -21001, "park", nil}, + }) + }) + + t.Run("OldStyleMpRelationWayInserted", func(t *testing.T) { + // Old-style-mp: Part of relation is now inserted. + ts.assertRecords(t, []checkElem{ + {"osm_landusages", -9001, "park", map[string]string{"name": "rel 9001"}}, + {"osm_landusages", 9009, "park", map[string]string{"name": "way 9009"}}, + {"osm_landusages", -9101, "park", map[string]string{"name": "rel 9101"}}, + {"osm_landusages", 9109, "park", map[string]string{"name": "way 9109"}}, + {"osm_landusages", 9110, "scrub", nil}, + }) + }) + + t.Run("RelationWaysInserted", func(t *testing.T) { + // Outer ways of multipolygon are inserted. + ts.assertRecords(t, []checkElem{ + // no name on relation + {"osm_landusages", -9201, "park", map[string]string{"name": ""}}, + {"osm_landusages", 9201, Missing, nil}, + {"osm_landusages", 9209, Missing, nil}, + {"osm_landusages", 9210, Missing, nil}, + // outer ways of multipolygon stand for their own + {"osm_roads", 9209, "secondary", map[string]string{"name": "9209"}}, + {"osm_roads", 9210, "residential", map[string]string{"name": "9210"}}, + }) + }) + + t.Run("RelationWayInserted", func(t *testing.T) { + // Part of relation was inserted twice. + ts.assertRecords(t, []checkElem{ + {"osm_landusages", -8001, "park", map[string]string{"name": "rel 8001"}}, + {"osm_roads", 8009, "residential", nil}, + }) + }) + + t.Run("SingleNodeWaysNotInserted", func(t *testing.T) { + // Ways with single/duplicate nodes are not inserted. + ts.assertRecords(t, []checkElem{ + {"osm_landusages", 30001, Missing, nil}, + {"osm_landusages", 30002, Missing, nil}, + {"osm_landusages", 30003, Missing, nil}, + }) + }) + + t.Run("PolygonWithDuplicateNodesIsValid", func(t *testing.T) { + // Polygon with duplicate nodes is valid. + ts.assertGeomValid(t, checkElem{"osm_landusages", 30005, "park", nil}) + }) + + t.Run("IncompletePolygons", func(t *testing.T) { + // Non-closed/incomplete polygons are not inserted. + + ts.assertRecords(t, []checkElem{ + {"osm_landusages", 30004, Missing, nil}, + {"osm_landusages", 30006, Missing, nil}, + }) + }) + + t.Run("ResidentialToSecondary", func(t *testing.T) { + // Residential road is not in roads_gen0/1. + + ts.assertRecords(t, []checkElem{ + {"osm_roads", 40001, "residential", nil}, + {"osm_roads_gen0", 40001, Missing, nil}, + {"osm_roads_gen1", 40002, Missing, nil}, + }) + }) + + t.Run("RelationBeforeRemove", func(t *testing.T) { + // Relation and way is inserted. + + ts.assertRecords(t, []checkElem{ + {"osm_buildings", 50011, "yes", nil}, + {"osm_landusages", -50021, "park", nil}, + }) + }) + + t.Run("OldStyleRelationIsIgnored", func(t *testing.T) { + // Relation without tags is not inserted. + + ts.assertRecords(t, []checkElem{ + {"osm_buildings", 50111, "yes", nil}, + {"osm_buildings", -50121, Missing, nil}, + }) + }) + + t.Run("DuplicateIds", func(t *testing.T) { + // Relation/way with same ID is inserted. + + ts.assertRecords(t, []checkElem{ + {"osm_buildings", 51001, "way", nil}, + {"osm_buildings", -51001, "mp", nil}, + {"osm_buildings", 51011, "way", nil}, + {"osm_buildings", -51011, "mp", nil}, + }) + }) + + t.Run("RelationUpdatedByNode", func(t *testing.T) { + // Relations was updated after modified node. + + ts.assertGeomArea(t, checkElem{"osm_buildings", -52121, "yes", nil}, 13653930440.868315) + }) + + t.Run("GeneralizedBananaPolygonIsValid", func(t *testing.T) { + // Generalized polygons are valid. + + ts.assertGeomValid(t, checkElem{"osm_landusages", 7101, Missing, nil}) + // simplified geometies are valid too + ts.assertGeomValid(t, checkElem{"osm_landusages_gen0", 7101, Missing, nil}) + ts.assertGeomValid(t, checkElem{"osm_landusages_gen1", 7101, Missing, nil}) + }) + + t.Run("GeneralizedLinestringIsValid", func(t *testing.T) { + // Generalized linestring is valid. + + // geometry is not simple, but valid + ts.assertGeomLength(t, checkElem{"osm_roads", 7201, "primary", nil}, 1243660.044819) + if ts.g.IsSimple(ts.queryGeom(t, "osm_roads", 7201)) { + t.Errorf("expected non-simple geometry for 7201") + } + // check that geometry 'survives' simplification + ts.assertGeomLength(t, checkElem{"osm_roads_gen0", 7201, "primary", nil}, 1243660.044819) + ts.assertGeomLength(t, checkElem{"osm_roads_gen1", 7201, "primary", nil}, 1243660.044819) + }) + + t.Run("RingWithGap", func(t *testing.T) { + // Multipolygon with gap (overlapping but different endpoints) gets closed + ts.assertGeomValid(t, checkElem{"osm_landusages", -7301, Missing, nil}) + // but not way + ts.assertRecords(t, []checkElem{ + checkElem{"osm_landusages", 7311, Missing, nil}, + }) + }) + + t.Run("MultipolygonWithOpenRing", func(t *testing.T) { + // Multipolygon is inserted even if there is an open ring/member + ts.assertGeomValid(t, checkElem{"osm_landusages", -7401, Missing, nil}) + }) + + t.Run("UpdatedNodes1", func(t *testing.T) { + // Zig-Zag line is inserted. + ts.assertGeomLength(t, checkElem{"osm_roads", 60000, Missing, nil}, 14035.61150207768) + }) + + t.Run("UpdateNodeToCoord1", func(t *testing.T) { + // Node is inserted with tag. + ts.assertRecords(t, []checkElem{ + {"osm_amenities", 70001, "police", nil}, + {"osm_amenities", 70002, Missing, nil}, + }) + }) + + t.Run("EnumerateKey", func(t *testing.T) { + // Enumerate from key. + ts.assertRecords(t, []checkElem{ + {"osm_landusages", 100001, "park", map[string]string{"enum": "1"}}, + {"osm_landusages", 100002, "park", map[string]string{"enum": "0"}}, + {"osm_landusages", 100003, "wood", map[string]string{"enum": "15"}}, + }) + }) + + t.Run("AreaMapping", func(t *testing.T) { + // Mapping type dependent area-defaults. + + ts.assertRecords(t, []checkElem{ + // highway=pedestrian + {"osm_roads", 301151, "pedestrian", nil}, + {"osm_landusages", 301151, Missing, nil}, + + // // highway=pedestrian, area=yes + {"osm_roads", 301152, Missing, nil}, + {"osm_landusages", 301152, "pedestrian", nil}, + + // // leisure=track + {"osm_roads", 301153, Missing, nil}, + {"osm_landusages", 301153, "track", nil}, + + // // leisure=track, area=no + {"osm_roads", 301154, "track", nil}, + {"osm_landusages", 301154, Missing, nil}, + }) + }) + + t.Run("HstoreTags", func(t *testing.T) { + // Mapping type dependent area-defaults. + + ts.assertHstore(t, []checkElem{ + {"osm_buildings", 401151, "*", map[string]string{"amenity": "fuel", "opening_hours": "24/7"}}, + }) + }) + + // ####################################################################### + + t.Run("Update", func(t *testing.T) { + ts.updateOsm(t, "build/complete_db.osc.gz") + }) + + // ####################################################################### + + t.Run("NoDuplicates", func(t *testing.T) { + // Relations/ways are only inserted once Checks #66 + + for _, table := range []string{"osm_roads", "osm_landusages"} { + rows, err := ts.db.Query( + fmt.Sprintf(`SELECT osm_id, count(osm_id) FROM "%s"."%s" GROUP BY osm_id HAVING count(osm_id) > 1`, + ts.dbschemaProduction(), table)) + if err != nil { t.Fatal(err) } - if table == "osm_roads" && osmId == 18001 { - // # duplicate for TestNodeWayInsertedTwice is expected - if count != 2 { - t.Error("highway not inserted twice", osmId, count) + var osmId, count int64 + for rows.Next() { + if err := rows.Scan(&osmId, &count); err != nil { + t.Fatal(err) + } + if table == "osm_roads" && osmId == 18001 { + // # duplicate for TestNodeWayInsertedTwice is expected + if count != 2 { + t.Error("highway not inserted twice", osmId, count) + } + } else { + t.Error("found duplicate way in osm_roads", osmId, count) } - } else { - t.Error("found duplicate way in osm_roads", osmId, count) } } - } -} + }) -func TestComplete_UpdatedLandusage(t *testing.T) { - // Multipolygon relation was modified + t.Run("UpdatedLandusage", func(t *testing.T) { + // Multipolygon relation was modified - nd := element.Node{Long: 13.4, Lat: 47.5} - proj.NodeToMerc(&nd) - point, err := geom.Point(ts.g, nd) - if err != nil { - t.Fatal(err) - } - poly := ts.queryGeom(t, "osm_landusages", -1001) - // point not in polygon after update - if ts.g.Intersects(point, poly) { - t.Error("point intersects polygon") - } -} + nd := element.Node{Long: 13.4, Lat: 47.5} + proj.NodeToMerc(&nd) + point, err := geom.Point(ts.g, nd) + if err != nil { + t.Fatal(err) + } + poly := ts.queryGeom(t, "osm_landusages", -1001) + // point not in polygon after update + if ts.g.Intersects(point, poly) { + t.Error("point intersects polygon") + } + }) -func TestComplete_PartialDelete(t *testing.T) { - // Deleted relation but nodes are still cached + t.Run("PartialDelete", func(t *testing.T) { + // Deleted relation but nodes are still cached - cache := ts.cache(t) - defer cache.Close() - assertCachedNode(t, cache, 2001) - assertCachedWay(t, cache, 2001) - assertCachedWay(t, cache, 2002) + cache := ts.cache(t) + defer cache.Close() + ts.assertCachedNode(t, cache, 2001) + ts.assertCachedWay(t, cache, 2001) + ts.assertCachedWay(t, cache, 2002) - assertRecords(t, []checkElem{ - {"osm_landusages", -2001, Missing, nil}, - {"osm_landusages", 2001, Missing, nil}, + ts.assertRecords(t, []checkElem{ + {"osm_landusages", -2001, Missing, nil}, + {"osm_landusages", 2001, Missing, nil}, + }) + }) + + t.Run("UpdatedNodes", func(t *testing.T) { + // Nodes were added, modified or deleted + + c := ts.cache(t) + defer c.Close() + if _, err := c.Coords.GetCoord(10000); err != cache.NotFound { + t.Fatal("coord not missing") + } + + ts.assertRecords(t, []checkElem{ + {"osm_places", 10001, "village", map[string]string{"name": "Bar"}}, + {"osm_places", 10002, "city", map[string]string{"name": "Baz"}}, + }) + }) + + t.Run("LandusageToWaterarea2", func(t *testing.T) { + // Parks converted to water moved from landusages to waterareas + + ts.assertRecords(t, []checkElem{ + {"osm_waterareas", 11001, "water", nil}, + {"osm_waterareas", -13001, "water", nil}, + + {"osm_waterareas_gen0", 11001, "water", nil}, + {"osm_waterareas_gen0", -13001, "water", nil}, + + {"osm_waterareas_gen1", 11001, "water", nil}, + {"osm_waterareas_gen1", -13001, "water", nil}, + + {"osm_landusages", 11001, Missing, nil}, + {"osm_landusages", -13001, Missing, nil}, + + {"osm_landusages_gen0", 11001, Missing, nil}, + {"osm_landusages_gen0", -13001, Missing, nil}, + + {"osm_landusages_gen1", 11001, Missing, nil}, + {"osm_landusages_gen1", -13001, Missing, nil}, + }) + }) + + t.Run("ChangedHoleTags2", func(t *testing.T) { + // Newly tagged hole is inserted + + cache := ts.cache(t) + defer cache.Close() + ts.assertCachedWay(t, cache, 14001) + ts.assertCachedWay(t, cache, 14011) + + ts.assertGeomArea(t, checkElem{"osm_waterareas", 14011, "water", nil}, 26672019779) + ts.assertGeomArea(t, checkElem{"osm_landusages", -14001, "park", nil}, 10373697182) + + ts.assertRecords(t, []checkElem{ + {"osm_waterareas", -14011, Missing, nil}, + {"osm_landusages", -14001, "park", nil}, + }) + }) + + t.Run("SplitOuterMultipolygonWay2", func(t *testing.T) { + // Splitted outer way of multipolygon was inserted + + diffCache := ts.diffCache(t) + defer diffCache.Close() + if ids := diffCache.Ways.Get(15001); len(ids) != 1 || ids[0] != 15001 { + t.Error("way does not references relation") + } + if ids := diffCache.Ways.Get(15002); len(ids) != 1 || ids[0] != 15001 { + t.Error("way does not references relation") + } + + ts.assertRecords(t, []checkElem{ + {"osm_landusages", 15001, Missing, nil}, + {"osm_roads", 15002, "residential", nil}, + }) + ts.assertGeomArea(t, checkElem{"osm_landusages", -15001, "park", nil}, 9816216452) + }) + + t.Run("MergeOuterMultipolygonWay2", func(t *testing.T) { + // Merged outer way of multipolygon was inserted + + diffCache := ts.diffCache(t) + defer diffCache.Close() + if ids := diffCache.Ways.Get(16001); len(ids) != 1 || ids[0] != 16001 { + t.Error("way does not references relation") + } + if ids := diffCache.Ways.Get(16002); len(ids) != 0 { + t.Error("way references relation") + } + + cache := ts.cache(t) + defer cache.Close() + rel, err := cache.Relations.GetRelation(16001) + if err != nil { + t.Fatal(err) + } + if len(rel.Members) != 2 || rel.Members[0].Id != 16001 || rel.Members[1].Id != 16011 { + t.Error("unexpected relation members", rel) + } + + ts.assertRecords(t, []checkElem{ + {"osm_landusages", 16001, Missing, nil}, + {"osm_roads", 16002, Missing, nil}, + }) + ts.assertGeomArea(t, checkElem{"osm_landusages", -16001, "park", nil}, 12779350582) + }) + + t.Run("NodeWayRefAfterDelete2", func(t *testing.T) { + // Node does not referece deleted way + + diffCache := ts.diffCache(t) + defer diffCache.Close() + if ids := diffCache.Coords.Get(20001); len(ids) != 0 { + t.Error("node references way") + } + c := ts.cache(t) + defer c.Close() + _, err := c.Coords.GetCoord(20002) + if err != cache.NotFound { + t.Error("found deleted node") + } + + ts.assertRecords(t, []checkElem{ + {"osm_roads", 20001, Missing, nil}, + {"osm_barrierpoints", 20001, "block", nil}, + }) + }) + + t.Run("WayRelRefAfterDelete2", func(t *testing.T) { + // Way does not referece deleted relation + + diffCache := ts.diffCache(t) + defer diffCache.Close() + if ids := diffCache.Ways.Get(21001); len(ids) != 0 { + t.Error("way references relation") + } + + ts.assertRecords(t, []checkElem{ + {"osm_roads", 21001, "residential", nil}, + {"osm_landusages", 21001, Missing, nil}, + {"osm_landusages", -21001, Missing, nil}, + }) + }) + + t.Run("ResidentialToSecondary2", func(t *testing.T) { + // New secondary (from residential) is now in roads_gen0/1. + + ts.assertRecords(t, []checkElem{ + {"osm_roads", 40001, "secondary", nil}, + {"osm_roads_gen0", 40001, "secondary", nil}, + {"osm_roads_gen1", 40001, "secondary", nil}, + }) + }) + + t.Run("RelationAfterRemove", func(t *testing.T) { + // Relation is deleted and way is still present. + ts.assertRecords(t, []checkElem{ + {"osm_buildings", 50011, "yes", nil}, + {"osm_landusages", 50021, Missing, nil}, + {"osm_landusages", -50021, Missing, nil}, + }) + }) + + t.Run("RelationWithoutTags2", func(t *testing.T) { + // Relation without tags is removed. + + c := ts.cache(t) + defer c.Close() + ts.assertCachedWay(t, c, 50111) + + _, err := c.Ways.GetWay(20002) + if err != cache.NotFound { + t.Error("found deleted node") + } + + ts.assertRecords(t, []checkElem{ + {"osm_buildings", 50111, "yes", nil}, + {"osm_buildings", 50121, Missing, nil}, + {"osm_buildings", -50121, Missing, nil}, + }) + }) + + t.Run("DuplicateIds2", func(t *testing.T) { + // Only relation/way with same ID was deleted. + + ts.assertRecords(t, []checkElem{ + {"osm_buildings", 51001, "way", nil}, + {"osm_buildings", -51001, Missing, nil}, + {"osm_buildings", 51011, Missing, nil}, + {"osm_buildings", -51011, "mp", nil}, + }) + }) + + t.Run("RelationUpdatedByNode2", func(t *testing.T) { + // Relations was updated after modified node. + + ts.assertGeomArea(t, checkElem{"osm_buildings", -52121, "yes", nil}, 16276875196.653734) + }) + + t.Run("UpdatedWay2", func(t *testing.T) { + // All nodes of straightened way are updated. + + // new length 0.1 degree + ts.assertGeomLength(t, checkElem{"osm_roads", 60000, "park", nil}, 20037508.342789244/180.0/10.0) + }) + + t.Run("UpdateNodeToCoord2", func(t *testing.T) { + // Node is becomes coord after tags are removed. + + ts.assertRecords(t, []checkElem{ + {"osm_amenities", 70001, Missing, nil}, + {"osm_amenities", 70002, "police", nil}, + }) + }) + + t.Run("NoDuplicateInsert", func(t *testing.T) { + // Relation is not inserted again if a nother relation with the same way was modified + // Checks #65 + + ts.assertRecords(t, []checkElem{ + {"osm_landusages", -201191, "park", nil}, + {"osm_landusages", -201192, "forest", nil}, + {"osm_roads", 201151, "residential", nil}, + }) + }) + + t.Run("UnsupportedRelation", func(t *testing.T) { + // Unsupported relation type is not inserted with update + + ts.assertRecords(t, []checkElem{ + {"osm_landusages", -201291, Missing, nil}, + {"osm_landusages", 201251, "park", nil}, + }) + }) + + // ####################################################################### + + t.Run("DeployRevert", func(t *testing.T) { + if ts.tableExists(t, ts.dbschemaImport(), "osm_roads") { + t.Fatalf("table osm_roads exists in schema %s", ts.dbschemaImport()) + } + if !ts.tableExists(t, ts.dbschemaProduction(), "osm_roads") { + t.Fatalf("table osm_roads does not exists in schema %s", ts.dbschemaProduction()) + } + if ts.tableExists(t, ts.dbschemaBackup(), "osm_roads") { + t.Fatalf("table osm_roads exists in schema %s", ts.dbschemaBackup()) + } + + ts.importOsm(t) + + if !ts.tableExists(t, ts.dbschemaImport(), "osm_roads") { + t.Fatalf("table osm_roads does not exists in schema %s", ts.dbschemaImport()) + } + if !ts.tableExists(t, ts.dbschemaProduction(), "osm_roads") { + t.Fatalf("table osm_roads does not exists in schema %s", ts.dbschemaProduction()) + } + if ts.tableExists(t, ts.dbschemaBackup(), "osm_roads") { + t.Fatalf("table osm_roads exists in schema %s", ts.dbschemaBackup()) + } + + ts.deployOsm(t) + + if ts.tableExists(t, ts.dbschemaImport(), "osm_roads") { + t.Fatalf("table osm_roads exists in schema %s", ts.dbschemaImport()) + } + if !ts.tableExists(t, ts.dbschemaProduction(), "osm_roads") { + t.Fatalf("table osm_roads does not exists in schema %s", ts.dbschemaProduction()) + } + if !ts.tableExists(t, ts.dbschemaBackup(), "osm_roads") { + t.Fatalf("table osm_roads does exists in schema %s", ts.dbschemaBackup()) + } + + ts.revertDeployOsm(t) + + if !ts.tableExists(t, ts.dbschemaImport(), "osm_roads") { + t.Fatalf("table osm_roads does not exists in schema %s", ts.dbschemaImport()) + } + if !ts.tableExists(t, ts.dbschemaProduction(), "osm_roads") { + t.Fatalf("table osm_roads does not exists in schema %s", ts.dbschemaProduction()) + } + if ts.tableExists(t, ts.dbschemaBackup(), "osm_roads") { + t.Fatalf("table osm_roads exists in schema %s", ts.dbschemaBackup()) + } + }) + + t.Run("RemoveBackup", func(t *testing.T) { + if !ts.tableExists(t, ts.dbschemaImport(), "osm_roads") { + t.Fatalf("table osm_roads does not exists in schema %s", ts.dbschemaImport()) + } + if !ts.tableExists(t, ts.dbschemaProduction(), "osm_roads") { + t.Fatalf("table osm_roads does not exists in schema %s", ts.dbschemaProduction()) + } + if ts.tableExists(t, ts.dbschemaBackup(), "osm_roads") { + t.Fatalf("table osm_roads exists in schema %s", ts.dbschemaBackup()) + } + + ts.deployOsm(t) + + if ts.tableExists(t, ts.dbschemaImport(), "osm_roads") { + t.Fatalf("table osm_roads exists in schema %s", ts.dbschemaImport()) + } + if !ts.tableExists(t, ts.dbschemaProduction(), "osm_roads") { + t.Fatalf("table osm_roads does not exists in schema %s", ts.dbschemaProduction()) + } + if !ts.tableExists(t, ts.dbschemaBackup(), "osm_roads") { + t.Fatalf("table osm_roads does exists in schema %s", ts.dbschemaBackup()) + } + + ts.removeBackupOsm(t) + + if ts.tableExists(t, ts.dbschemaImport(), "osm_roads") { + t.Fatalf("table osm_roads exists in schema %s", ts.dbschemaImport()) + } + if !ts.tableExists(t, ts.dbschemaProduction(), "osm_roads") { + t.Fatalf("table osm_roads does not exists in schema %s", ts.dbschemaProduction()) + } + if ts.tableExists(t, ts.dbschemaBackup(), "osm_roads") { + t.Fatalf("table osm_roads exists in schema %s", ts.dbschemaBackup()) + } + }) + + t.Run("Cleanup", func(t *testing.T) { + ts.dropSchemas() + if err := os.RemoveAll(ts.dir); err != nil { + t.Error(err) + } }) } - -func TestComplete_UpdatedNodes(t *testing.T) { - // Nodes were added, modified or deleted - - c := ts.cache(t) - defer c.Close() - if _, err := c.Coords.GetCoord(10000); err != cache.NotFound { - t.Fatal("coord not missing") - } - - assertRecords(t, []checkElem{ - {"osm_places", 10001, "village", map[string]string{"name": "Bar"}}, - {"osm_places", 10002, "city", map[string]string{"name": "Baz"}}, - }) -} - -func TestComplete_LandusageToWaterarea2(t *testing.T) { - // Parks converted to water moved from landusages to waterareas - - assertRecords(t, []checkElem{ - {"osm_waterareas", 11001, "water", nil}, - {"osm_waterareas", -13001, "water", nil}, - - {"osm_waterareas_gen0", 11001, "water", nil}, - {"osm_waterareas_gen0", -13001, "water", nil}, - - {"osm_waterareas_gen1", 11001, "water", nil}, - {"osm_waterareas_gen1", -13001, "water", nil}, - - {"osm_landusages", 11001, Missing, nil}, - {"osm_landusages", -13001, Missing, nil}, - - {"osm_landusages_gen0", 11001, Missing, nil}, - {"osm_landusages_gen0", -13001, Missing, nil}, - - {"osm_landusages_gen1", 11001, Missing, nil}, - {"osm_landusages_gen1", -13001, Missing, nil}, - }) -} - -func TestComplete_ChangedHoleTags2(t *testing.T) { - // Newly tagged hole is inserted - - cache := ts.cache(t) - defer cache.Close() - assertCachedWay(t, cache, 14001) - assertCachedWay(t, cache, 14011) - - assertGeomArea(t, checkElem{"osm_waterareas", 14011, "water", nil}, 26672019779) - assertGeomArea(t, checkElem{"osm_landusages", -14001, "park", nil}, 10373697182) - - assertRecords(t, []checkElem{ - {"osm_waterareas", -14011, Missing, nil}, - {"osm_landusages", -14001, "park", nil}, - }) -} - -func TestComplete_SplitOuterMultipolygonWay2(t *testing.T) { - // Splitted outer way of multipolygon was inserted - - diffCache := ts.diffCache(t) - defer diffCache.Close() - if ids := diffCache.Ways.Get(15001); len(ids) != 1 || ids[0] != 15001 { - t.Error("way does not references relation") - } - if ids := diffCache.Ways.Get(15002); len(ids) != 1 || ids[0] != 15001 { - t.Error("way does not references relation") - } - - assertRecords(t, []checkElem{ - {"osm_landusages", 15001, Missing, nil}, - {"osm_roads", 15002, "residential", nil}, - }) - assertGeomArea(t, checkElem{"osm_landusages", -15001, "park", nil}, 9816216452) -} - -func TestComplete_MergeOuterMultipolygonWay2(t *testing.T) { - // Merged outer way of multipolygon was inserted - - diffCache := ts.diffCache(t) - defer diffCache.Close() - if ids := diffCache.Ways.Get(16001); len(ids) != 1 || ids[0] != 16001 { - t.Error("way does not references relation") - } - if ids := diffCache.Ways.Get(16002); len(ids) != 0 { - t.Error("way references relation") - } - - cache := ts.cache(t) - defer cache.Close() - rel, err := cache.Relations.GetRelation(16001) - if err != nil { - t.Fatal(err) - } - if len(rel.Members) != 2 || rel.Members[0].Id != 16001 || rel.Members[1].Id != 16011 { - t.Error("unexpected relation members", rel) - } - - assertRecords(t, []checkElem{ - {"osm_landusages", 16001, Missing, nil}, - {"osm_roads", 16002, Missing, nil}, - }) - assertGeomArea(t, checkElem{"osm_landusages", -16001, "park", nil}, 12779350582) -} - -func TestComplete_NodeWayRefAfterDelete2(t *testing.T) { - // Node does not referece deleted way - - diffCache := ts.diffCache(t) - defer diffCache.Close() - if ids := diffCache.Coords.Get(20001); len(ids) != 0 { - t.Error("node references way") - } - c := ts.cache(t) - defer c.Close() - _, err := c.Coords.GetCoord(20002) - if err != cache.NotFound { - t.Error("found deleted node") - } - - assertRecords(t, []checkElem{ - {"osm_roads", 20001, Missing, nil}, - {"osm_barrierpoints", 20001, "block", nil}, - }) -} - -func TestComplete_WayRelRefAfterDelete2(t *testing.T) { - // Way does not referece deleted relation - - diffCache := ts.diffCache(t) - defer diffCache.Close() - if ids := diffCache.Ways.Get(21001); len(ids) != 0 { - t.Error("way references relation") - } - - assertRecords(t, []checkElem{ - {"osm_roads", 21001, "residential", nil}, - {"osm_landusages", 21001, Missing, nil}, - {"osm_landusages", -21001, Missing, nil}, - }) -} - -func TestComplete_ResidentialToSecondary2(t *testing.T) { - // New secondary (from residential) is now in roads_gen0/1. - - assertRecords(t, []checkElem{ - {"osm_roads", 40001, "secondary", nil}, - {"osm_roads_gen0", 40001, "secondary", nil}, - {"osm_roads_gen1", 40001, "secondary", nil}, - }) -} - -func TestComplete_RelationAfterRemove(t *testing.T) { - // Relation is deleted and way is still present. - assertRecords(t, []checkElem{ - {"osm_buildings", 50011, "yes", nil}, - {"osm_landusages", 50021, Missing, nil}, - {"osm_landusages", -50021, Missing, nil}, - }) -} - -func TestComplete_RelationWithoutTags2(t *testing.T) { - // Relation without tags is removed. - - c := ts.cache(t) - defer c.Close() - assertCachedWay(t, c, 50111) - - _, err := c.Ways.GetWay(20002) - if err != cache.NotFound { - t.Error("found deleted node") - } - - assertRecords(t, []checkElem{ - {"osm_buildings", 50111, "yes", nil}, - {"osm_buildings", 50121, Missing, nil}, - {"osm_buildings", -50121, Missing, nil}, - }) -} - -func TestComplete_DuplicateIds2(t *testing.T) { - // Only relation/way with same ID was deleted. - - assertRecords(t, []checkElem{ - {"osm_buildings", 51001, "way", nil}, - {"osm_buildings", -51001, Missing, nil}, - {"osm_buildings", 51011, Missing, nil}, - {"osm_buildings", -51011, "mp", nil}, - }) -} - -func TestComplete_RelationUpdatedByNode2(t *testing.T) { - // Relations was updated after modified node. - - assertGeomArea(t, checkElem{"osm_buildings", -52121, "yes", nil}, 16276875196.653734) -} - -func TestComplete_UpdatedWay2(t *testing.T) { - // All nodes of straightened way are updated. - - // new length 0.1 degree - assertGeomLength(t, checkElem{"osm_roads", 60000, "park", nil}, 20037508.342789244/180.0/10.0) -} - -func TestComplete_UpdateNodeToCoord2(t *testing.T) { - // Node is becomes coord after tags are removed. - - assertRecords(t, []checkElem{ - {"osm_amenities", 70001, Missing, nil}, - {"osm_amenities", 70002, "police", nil}, - }) -} - -func TestComplete_NoDuplicateInsert(t *testing.T) { - // Relation is not inserted again if a nother relation with the same way was modified - // Checks #65 - - assertRecords(t, []checkElem{ - {"osm_landusages", -201191, "park", nil}, - {"osm_landusages", -201192, "forest", nil}, - {"osm_roads", 201151, "residential", nil}, - }) -} - -func TestComplete_UnsupportedRelation(t *testing.T) { - // Unsupported relation type is not inserted with update - - assertRecords(t, []checkElem{ - {"osm_landusages", -201291, Missing, nil}, - {"osm_landusages", 201251, "park", nil}, - }) -} - -// ####################################################################### - -func TestComplete_DeployRevert(t *testing.T) { - if ts.tableExists(t, dbschemaImport, "osm_roads") { - t.Fatalf("table osm_roads exists in schema %s", dbschemaImport) - } - if !ts.tableExists(t, dbschemaProduction, "osm_roads") { - t.Fatalf("table osm_roads does not exists in schema %s", dbschemaProduction) - } - if ts.tableExists(t, dbschemaBackup, "osm_roads") { - t.Fatalf("table osm_roads exists in schema %s", dbschemaBackup) - } - - ts.importOsm(t) - - if !ts.tableExists(t, dbschemaImport, "osm_roads") { - t.Fatalf("table osm_roads does not exists in schema %s", dbschemaImport) - } - if !ts.tableExists(t, dbschemaProduction, "osm_roads") { - t.Fatalf("table osm_roads does not exists in schema %s", dbschemaProduction) - } - if ts.tableExists(t, dbschemaBackup, "osm_roads") { - t.Fatalf("table osm_roads exists in schema %s", dbschemaBackup) - } - - ts.deployOsm(t) - - if ts.tableExists(t, dbschemaImport, "osm_roads") { - t.Fatalf("table osm_roads exists in schema %s", dbschemaImport) - } - if !ts.tableExists(t, dbschemaProduction, "osm_roads") { - t.Fatalf("table osm_roads does not exists in schema %s", dbschemaProduction) - } - if !ts.tableExists(t, dbschemaBackup, "osm_roads") { - t.Fatalf("table osm_roads does exists in schema %s", dbschemaBackup) - } - - ts.revertDeployOsm(t) - - if !ts.tableExists(t, dbschemaImport, "osm_roads") { - t.Fatalf("table osm_roads does not exists in schema %s", dbschemaImport) - } - if !ts.tableExists(t, dbschemaProduction, "osm_roads") { - t.Fatalf("table osm_roads does not exists in schema %s", dbschemaProduction) - } - if ts.tableExists(t, dbschemaBackup, "osm_roads") { - t.Fatalf("table osm_roads exists in schema %s", dbschemaBackup) - } -} - -func TestComplete_RemoveBackup(t *testing.T) { - if !ts.tableExists(t, dbschemaImport, "osm_roads") { - t.Fatalf("table osm_roads does not exists in schema %s", dbschemaImport) - } - if !ts.tableExists(t, dbschemaProduction, "osm_roads") { - t.Fatalf("table osm_roads does not exists in schema %s", dbschemaProduction) - } - if ts.tableExists(t, dbschemaBackup, "osm_roads") { - t.Fatalf("table osm_roads exists in schema %s", dbschemaBackup) - } - - ts.deployOsm(t) - - if ts.tableExists(t, dbschemaImport, "osm_roads") { - t.Fatalf("table osm_roads exists in schema %s", dbschemaImport) - } - if !ts.tableExists(t, dbschemaProduction, "osm_roads") { - t.Fatalf("table osm_roads does not exists in schema %s", dbschemaProduction) - } - if !ts.tableExists(t, dbschemaBackup, "osm_roads") { - t.Fatalf("table osm_roads does exists in schema %s", dbschemaBackup) - } - - ts.removeBackupOsm(t) - - if ts.tableExists(t, dbschemaImport, "osm_roads") { - t.Fatalf("table osm_roads exists in schema %s", dbschemaImport) - } - if !ts.tableExists(t, dbschemaProduction, "osm_roads") { - t.Fatalf("table osm_roads does not exists in schema %s", dbschemaProduction) - } - if ts.tableExists(t, dbschemaBackup, "osm_roads") { - t.Fatalf("table osm_roads exists in schema %s", dbschemaBackup) - } -} - -func TestComplete_Cleanup(t *testing.T) { - ts.dropSchemas() - if err := os.RemoveAll(ts.dir); err != nil { - t.Error(err) - } -} diff --git a/test/expire_tiles_test.go b/test/expire_tiles_test.go index 1b2fca6..7fc0bd6 100644 --- a/test/expire_tiles_test.go +++ b/test/expire_tiles_test.go @@ -14,168 +14,178 @@ import ( "github.com/omniscale/imposm3/geom/geos" ) -func TestExpireTiles_Prepare(t *testing.T) { - var err error - - ts.dir, err = ioutil.TempDir("", "imposm_test") - if err != nil { - t.Fatal(err) +func TestExpireTiles(t *testing.T) { + if testing.Short() { + t.Skip("system test skipped with -test.short") } - ts.config = importConfig{ - connection: "postgis://", - cacheDir: ts.dir, - osmFileName: "build/expire_tiles.pbf", - mappingFileName: "expire_tiles_mapping.yml", - expireTileDir: filepath.Join(ts.dir, "expiretiles"), - } - ts.g = geos.NewGeos() - ts.db, err = sql.Open("postgres", "sslmode=disable") - if err != nil { - t.Fatal(err) + ts := importTestSuite{ + name: "expire_tiles", } - ts.dropSchemas() -} -func TestExpireTiles_Import(t *testing.T) { - if ts.tableExists(t, dbschemaImport, "osm_roads") != false { - t.Fatalf("table osm_roads exists in schema %s", dbschemaImport) - } - ts.importOsm(t) - ts.deployOsm(t) - if ts.tableExists(t, dbschemaProduction, "osm_roads") != true { - t.Fatalf("table osm_roads does not exists in schema %s", dbschemaProduction) - } -} + t.Run("Prepare", func(t *testing.T) { + var err error -func TestExpireTiles_Elements(t *testing.T) { - assertRecords(t, []checkElem{ - {"osm_roads", 20151, "motorway", nil}, - {"osm_roads", 20251, "motorway", nil}, - {"osm_roads", 20351, "motorway", nil}, + ts.dir, err = ioutil.TempDir("", "imposm_test") + if err != nil { + t.Fatal(err) + } + ts.config = importConfig{ + connection: "postgis://", + cacheDir: ts.dir, + osmFileName: "build/expire_tiles.pbf", + mappingFileName: "expire_tiles_mapping.yml", + expireTileDir: filepath.Join(ts.dir, "expiretiles"), + } + ts.g = geos.NewGeos() - {"osm_buildings", -30191, "yes", nil}, - {"osm_buildings", -30291, "yes", nil}, - {"osm_buildings", -30391, "yes", nil}, - {"osm_buildings", -30491, "yes", nil}, + ts.db, err = sql.Open("postgres", "sslmode=disable") + if err != nil { + t.Fatal(err) + } + ts.dropSchemas() }) -} -func TestExpireTiles_Update(t *testing.T) { - ts.updateOsm(t, "build/expire_tiles.osc.gz") -} + t.Run("Import", func(t *testing.T) { + if ts.tableExists(t, ts.dbschemaImport(), "osm_roads") != false { + t.Fatalf("table osm_roads exists in schema %s", ts.dbschemaImport()) + } + ts.importOsm(t) + ts.deployOsm(t) + if ts.tableExists(t, ts.dbschemaProduction(), "osm_roads") != true { + t.Fatalf("table osm_roads does not exists in schema %s", ts.dbschemaProduction()) + } + }) -func TestExpireTiles_CheckExpireFile(t *testing.T) { - files, err := filepath.Glob(filepath.Join(ts.config.expireTileDir, "*", "*.tiles")) - if err != nil { - t.Fatal(err) - } - if len(files) != 1 { - t.Fatalf("expected one expire tile file, got: %v", files) - } - tiles, err := parseTileList(files[0]) - if err != nil { - t.Error(err) - } + t.Run("Elements", func(t *testing.T) { + ts.assertRecords(t, []checkElem{ + {"osm_roads", 20151, "motorway", nil}, + {"osm_roads", 20251, "motorway", nil}, + {"osm_roads", 20351, "motorway", nil}, - for _, test := range []struct { - reason string - tiles []tile - expire bool - }{ - {"create node", []tile{{8328, 8146, 14}}, true}, - {"modify node (old)", []tile{{8237, 8146, 14}}, true}, - {"modify node (new)", []tile{{8237, 8237, 14}}, true}, - {"modify node to unmapped (old)", []tile{{8373, 8146, 14}, {8374, 8146, 14}}, true}, - {"modify node to unmapped (new)", []tile{{8373, 8146, 14}, {8374, 8146, 14}}, false}, - {"delete node", []tile{{8282, 8146, 14}, {8283, 8146, 14}}, true}, + {"osm_buildings", -30191, "yes", nil}, + {"osm_buildings", -30291, "yes", nil}, + {"osm_buildings", -30391, "yes", nil}, + {"osm_buildings", -30491, "yes", nil}, + }) + }) - {"delete way", []tile{{8283, 8100, 14}}, true}, - {"modify way", []tile{{8237, 8100, 14}}, true}, - {"modify way from node (old)", []tile{{8328, 8100, 14}}, true}, - {"modify way from node (new)", []tile{{8328, 8283, 14}}, true}, - {"create way", []tile{{8374, 8100, 14}}, true}, - {"create long way", []tile{{8419, 8100, 14}, {8420, 8100, 14}, {8421, 8100, 14}}, true}, + t.Run("Update", func(t *testing.T) { + ts.updateOsm(t, "build/expire_tiles.osc.gz") + }) - {"modify relation", []tile{{8237, 8055, 14}}, true}, - {"delete relation", []tile{{8283, 8055, 14}}, true}, - {"modify relation from way", []tile{{8328, 8055, 14}}, true}, - {"modify relation from nodes (old)", []tile{{8374, 8055, 14}}, true}, - {"modify relation from nodes (new)", []tile{{8374, 8328, 14}}, true}, - {"create polygon (box)", []tile{ - {8237, 8007, 14}, - {8237, 8008, 14}, - {8237, 8009, 14}, - {8238, 8007, 14}, - {8238, 8008, 14}, - {8238, 8009, 14}, - {8239, 8007, 14}, - {8239, 8008, 14}, - {8239, 8009, 14}, - }, true}, + t.Run("CheckExpireFile", func(t *testing.T) { + files, err := filepath.Glob(filepath.Join(ts.config.expireTileDir, "*", "*.tiles")) + if err != nil { + t.Fatal(err) + } + if len(files) != 1 { + t.Fatalf("expected one expire tile file, got: %v", files) + } + tiles, err := parseTileList(files[0]) + if err != nil { + t.Error(err) + } - {"create polygon (outline)", []tile{ - {8310, 8005, 14}, {8302, 7991, 14}, {8283, 7993, 14}, - {8300, 8009, 14}, {8283, 8003, 14}, {8308, 8009, 14}, - {8310, 7995, 14}, {8285, 8009, 14}, {8288, 8009, 14}, - {8301, 8009, 14}, {8310, 8002, 14}, {8302, 8009, 14}, - {8310, 8003, 14}, {8286, 8009, 14}, {8300, 7991, 14}, - {8283, 7994, 14}, {8296, 8009, 14}, {8298, 8009, 14}, - {8310, 8009, 14}, {8283, 7999, 14}, {8283, 7992, 14}, - {8290, 7991, 14}, {8305, 8009, 14}, {8309, 7991, 14}, - {8306, 7991, 14}, {8291, 7991, 14}, {8283, 7996, 14}, - {8310, 7996, 14}, {8293, 7991, 14}, {8310, 8007, 14}, - {8310, 8001, 14}, {8307, 8009, 14}, {8299, 8009, 14}, - {8310, 7998, 14}, {8310, 7999, 14}, {8301, 7991, 14}, - {8283, 7998, 14}, {8283, 8006, 14}, {8289, 8009, 14}, - {8310, 8008, 14}, {8285, 7991, 14}, {8283, 8002, 14}, - {8289, 7991, 14}, {8286, 7991, 14}, {8288, 7991, 14}, - {8283, 8008, 14}, {8283, 8005, 14}, {8310, 7992, 14}, - {8310, 8004, 14}, {8310, 7991, 14}, {8296, 7991, 14}, - {8292, 7991, 14}, {8283, 8009, 14}, {8291, 8009, 14}, - {8293, 8009, 14}, {8284, 8009, 14}, {8287, 7991, 14}, - {8297, 8009, 14}, {8283, 8007, 14}, {8299, 7991, 14}, - {8310, 7997, 14}, {8303, 8009, 14}, {8290, 8009, 14}, - {8306, 8009, 14}, {8283, 7995, 14}, {8283, 8000, 14}, - {8295, 8009, 14}, {8310, 8006, 14}, {8304, 8009, 14}, - {8295, 7991, 14}, {8292, 8009, 14}, {8309, 8009, 14}, - {8283, 8004, 14}, {8307, 7991, 14}, {8305, 7991, 14}, - {8283, 8001, 14}, {8284, 7991, 14}, {8297, 7991, 14}, - {8310, 7993, 14}, {8303, 7991, 14}, {8294, 8009, 14}, - {8287, 8009, 14}, {8283, 7991, 14}, {8283, 7997, 14}, - {8308, 7991, 14}, {8304, 7991, 14}, {8298, 7991, 14}, - {8310, 8000, 14}, {8310, 7994, 14}, {8294, 7991, 14}, - }, true}, - } { + for _, test := range []struct { + reason string + tiles []tile + expire bool + }{ + {"create node", []tile{{8328, 8146, 14}}, true}, + {"modify node (old)", []tile{{8237, 8146, 14}}, true}, + {"modify node (new)", []tile{{8237, 8237, 14}}, true}, + {"modify node to unmapped (old)", []tile{{8373, 8146, 14}, {8374, 8146, 14}}, true}, + {"modify node to unmapped (new)", []tile{{8373, 8146, 14}, {8374, 8146, 14}}, false}, + {"delete node", []tile{{8282, 8146, 14}, {8283, 8146, 14}}, true}, - for _, coord := range test.tiles { - if test.expire { - if _, ok := tiles[coord]; !ok { - t.Errorf("missing expire tile for %s %v", test.reason, coord) + {"delete way", []tile{{8283, 8100, 14}}, true}, + {"modify way", []tile{{8237, 8100, 14}}, true}, + {"modify way from node (old)", []tile{{8328, 8100, 14}}, true}, + {"modify way from node (new)", []tile{{8328, 8283, 14}}, true}, + {"create way", []tile{{8374, 8100, 14}}, true}, + {"create long way", []tile{{8419, 8100, 14}, {8420, 8100, 14}, {8421, 8100, 14}}, true}, + + {"modify relation", []tile{{8237, 8055, 14}}, true}, + {"delete relation", []tile{{8283, 8055, 14}}, true}, + {"modify relation from way", []tile{{8328, 8055, 14}}, true}, + {"modify relation from nodes (old)", []tile{{8374, 8055, 14}}, true}, + {"modify relation from nodes (new)", []tile{{8374, 8328, 14}}, true}, + {"create polygon (box)", []tile{ + {8237, 8007, 14}, + {8237, 8008, 14}, + {8237, 8009, 14}, + {8238, 8007, 14}, + {8238, 8008, 14}, + {8238, 8009, 14}, + {8239, 8007, 14}, + {8239, 8008, 14}, + {8239, 8009, 14}, + }, true}, + + {"create polygon (outline)", []tile{ + {8310, 8005, 14}, {8302, 7991, 14}, {8283, 7993, 14}, + {8300, 8009, 14}, {8283, 8003, 14}, {8308, 8009, 14}, + {8310, 7995, 14}, {8285, 8009, 14}, {8288, 8009, 14}, + {8301, 8009, 14}, {8310, 8002, 14}, {8302, 8009, 14}, + {8310, 8003, 14}, {8286, 8009, 14}, {8300, 7991, 14}, + {8283, 7994, 14}, {8296, 8009, 14}, {8298, 8009, 14}, + {8310, 8009, 14}, {8283, 7999, 14}, {8283, 7992, 14}, + {8290, 7991, 14}, {8305, 8009, 14}, {8309, 7991, 14}, + {8306, 7991, 14}, {8291, 7991, 14}, {8283, 7996, 14}, + {8310, 7996, 14}, {8293, 7991, 14}, {8310, 8007, 14}, + {8310, 8001, 14}, {8307, 8009, 14}, {8299, 8009, 14}, + {8310, 7998, 14}, {8310, 7999, 14}, {8301, 7991, 14}, + {8283, 7998, 14}, {8283, 8006, 14}, {8289, 8009, 14}, + {8310, 8008, 14}, {8285, 7991, 14}, {8283, 8002, 14}, + {8289, 7991, 14}, {8286, 7991, 14}, {8288, 7991, 14}, + {8283, 8008, 14}, {8283, 8005, 14}, {8310, 7992, 14}, + {8310, 8004, 14}, {8310, 7991, 14}, {8296, 7991, 14}, + {8292, 7991, 14}, {8283, 8009, 14}, {8291, 8009, 14}, + {8293, 8009, 14}, {8284, 8009, 14}, {8287, 7991, 14}, + {8297, 8009, 14}, {8283, 8007, 14}, {8299, 7991, 14}, + {8310, 7997, 14}, {8303, 8009, 14}, {8290, 8009, 14}, + {8306, 8009, 14}, {8283, 7995, 14}, {8283, 8000, 14}, + {8295, 8009, 14}, {8310, 8006, 14}, {8304, 8009, 14}, + {8295, 7991, 14}, {8292, 8009, 14}, {8309, 8009, 14}, + {8283, 8004, 14}, {8307, 7991, 14}, {8305, 7991, 14}, + {8283, 8001, 14}, {8284, 7991, 14}, {8297, 7991, 14}, + {8310, 7993, 14}, {8303, 7991, 14}, {8294, 8009, 14}, + {8287, 8009, 14}, {8283, 7991, 14}, {8283, 7997, 14}, + {8308, 7991, 14}, {8304, 7991, 14}, {8298, 7991, 14}, + {8310, 8000, 14}, {8310, 7994, 14}, {8294, 7991, 14}, + }, true}, + } { + + for _, coord := range test.tiles { + if test.expire { + if _, ok := tiles[coord]; !ok { + t.Errorf("missing expire tile for %s %v", test.reason, coord) + } else { + delete(tiles, coord) + } } else { - delete(tiles, coord) - } - } else { - if _, ok := tiles[coord]; ok { - t.Errorf("found expire tile for %s %v", test.reason, coord) + if _, ok := tiles[coord]; ok { + t.Errorf("found expire tile for %s %v", test.reason, coord) + } } } } - } - if len(tiles) > 0 { - t.Errorf("found %d unexpected tiles", len(tiles)) - } - for tile, _ := range tiles { - t.Errorf("unexpected tile expired: %v", tile) - } -} + if len(tiles) > 0 { + t.Errorf("found %d unexpected tiles", len(tiles)) + } + for tile, _ := range tiles { + t.Errorf("unexpected tile expired: %v", tile) + } + }) -func TestExpireTiles_Cleanup(t *testing.T) { - ts.dropSchemas() - if err := os.RemoveAll(ts.dir); err != nil { - t.Error(err) - } + t.Run("Cleanup", func(t *testing.T) { + ts.dropSchemas() + if err := os.RemoveAll(ts.dir); err != nil { + t.Error(err) + } + }) } type tile struct { diff --git a/test/helper_test.go b/test/helper_test.go index 99d5392..348c955 100644 --- a/test/helper_test.go +++ b/test/helper_test.go @@ -21,12 +21,6 @@ import ( "github.com/omniscale/imposm3/import_" ) -const ( - dbschemaImport = "imposm_test_import" - dbschemaProduction = "imposm_test_production" - dbschemaBackup = "imposm_test_backup" -) - type importConfig struct { connection string osmFileName string @@ -38,6 +32,7 @@ type importConfig struct { type importTestSuite struct { dir string + name string config importConfig db *sql.DB g *geos.Geos @@ -45,6 +40,10 @@ type importTestSuite struct { const Missing = "" +func (s *importTestSuite) dbschemaImport() string { return "imposm_test_" + s.name + "_import" } +func (s *importTestSuite) dbschemaProduction() string { return "imposm_test_" + s.name + "_production" } +func (s *importTestSuite) dbschemaBackup() string { return "imposm_test_" + s.name + "_backup" } + func (s *importTestSuite) importOsm(t *testing.T) { importArgs := []string{ "-connection", s.config.connection, @@ -53,7 +52,7 @@ func (s *importTestSuite) importOsm(t *testing.T) { "-cachedir", s.config.cacheDir, "-diff", "-overwritecache", - "-dbschema-import", dbschemaImport, + "-dbschema-import", s.dbschemaImport(), // "-optimize", "-mapping", s.config.mappingFileName, "-quiet", @@ -75,9 +74,9 @@ func (s *importTestSuite) deployOsm(t *testing.T) { "-deployproduction", "-removebackup=false", "-connection", s.config.connection, - "-dbschema-import", dbschemaImport, - "-dbschema-production", dbschemaProduction, - "-dbschema-backup", dbschemaBackup, + "-dbschema-import", s.dbschemaImport(), + "-dbschema-production", s.dbschemaProduction(), + "-dbschema-backup", s.dbschemaBackup(), "-deployproduction", "-mapping", s.config.mappingFileName, "-quiet", @@ -96,9 +95,9 @@ func (s *importTestSuite) revertDeployOsm(t *testing.T) { "-deployproduction=false", "-removebackup=false", "-connection", s.config.connection, - "-dbschema-import", dbschemaImport, - "-dbschema-production", dbschemaProduction, - "-dbschema-backup", dbschemaBackup, + "-dbschema-import", s.dbschemaImport(), + "-dbschema-production", s.dbschemaProduction(), + "-dbschema-backup", s.dbschemaBackup(), "-revertdeploy", "-deployproduction=false", "-removebackup=false", @@ -135,9 +134,9 @@ func (s *importTestSuite) removeBackupOsm(t *testing.T) { "-deployproduction=false", "-removebackup", "-connection", s.config.connection, - "-dbschema-import", dbschemaImport, - "-dbschema-production", dbschemaProduction, - "-dbschema-backup", dbschemaBackup, + "-dbschema-import", s.dbschemaImport(), + "-dbschema-production", s.dbschemaProduction(), + "-dbschema-backup", s.dbschemaBackup(), "-mapping", s.config.mappingFileName, "-quiet", } @@ -151,7 +150,7 @@ func (s *importTestSuite) updateOsm(t *testing.T, diffFile string) { "-connection", s.config.connection, "-cachedir", s.config.cacheDir, "-limitto", "clipping.geojson", - "-dbschema-production", dbschemaProduction, + "-dbschema-production", s.dbschemaProduction(), "-mapping", s.config.mappingFileName, } if s.config.expireTileDir != "" { @@ -164,15 +163,15 @@ func (s *importTestSuite) updateOsm(t *testing.T, diffFile string) { func (s *importTestSuite) dropSchemas() { var err error - _, err = s.db.Exec(fmt.Sprintf(`DROP SCHEMA IF EXISTS %s CASCADE`, dbschemaImport)) + _, err = s.db.Exec(fmt.Sprintf(`DROP SCHEMA IF EXISTS %s CASCADE`, s.dbschemaImport())) if err != nil { log.Fatal(err) } - _, err = s.db.Exec(fmt.Sprintf(`DROP SCHEMA IF EXISTS %s CASCADE`, dbschemaProduction)) + _, err = s.db.Exec(fmt.Sprintf(`DROP SCHEMA IF EXISTS %s CASCADE`, s.dbschemaProduction())) if err != nil { log.Fatal(err) } - _, err = s.db.Exec(fmt.Sprintf(`DROP SCHEMA IF EXISTS %s CASCADE`, dbschemaBackup)) + _, err = s.db.Exec(fmt.Sprintf(`DROP SCHEMA IF EXISTS %s CASCADE`, s.dbschemaBackup())) if err != nil { log.Fatal(err) } @@ -208,7 +207,7 @@ func (s *importTestSuite) query(t *testing.T, table string, id int64, keys []str } else { columns = "hstore(ARRAY[" + columns + "])" } - stmt := fmt.Sprintf(`SELECT osm_id, name, type, ST_AsText(geometry), %s FROM "%s"."%s" WHERE osm_id=$1`, columns, dbschemaProduction, table) + stmt := fmt.Sprintf(`SELECT osm_id, name, type, ST_AsText(geometry), %s FROM "%s"."%s" WHERE osm_id=$1`, columns, s.dbschemaProduction(), table) row := s.db.QueryRow(stmt, id) r := record{} h := hstore.Hstore{} @@ -231,7 +230,7 @@ func (s *importTestSuite) query(t *testing.T, table string, id int64, keys []str } func (s *importTestSuite) queryTags(t *testing.T, table string, id int64) record { - stmt := fmt.Sprintf(`SELECT osm_id, tags FROM "%s"."%s" WHERE osm_id=$1`, dbschemaProduction, table) + stmt := fmt.Sprintf(`SELECT osm_id, tags FROM "%s"."%s" WHERE osm_id=$1`, s.dbschemaProduction(), table) row := s.db.QueryRow(stmt, id) r := record{} h := hstore.Hstore{} @@ -254,7 +253,7 @@ func (s *importTestSuite) queryTags(t *testing.T, table string, id int64) record } func (s *importTestSuite) queryRows(t *testing.T, table string, id int64) []record { - rows, err := s.db.Query(fmt.Sprintf(`SELECT osm_id, name, type, ST_AsText(geometry) FROM "%s"."%s" WHERE osm_id=$1 ORDER BY type, name, ST_GeometryType(geometry)`, dbschemaProduction, table), id) + rows, err := s.db.Query(fmt.Sprintf(`SELECT osm_id, name, type, ST_AsText(geometry) FROM "%s"."%s" WHERE osm_id=$1 ORDER BY type, name, ST_GeometryType(geometry)`, s.dbschemaProduction(), table), id) if err != nil { t.Fatal(err) } @@ -270,7 +269,7 @@ func (s *importTestSuite) queryRows(t *testing.T, table string, id int64) []reco } func (s *importTestSuite) queryRowsTags(t *testing.T, table string, id int64) []record { - rows, err := s.db.Query(fmt.Sprintf(`SELECT osm_id, ST_AsText(geometry), tags FROM "%s"."%s" WHERE osm_id=$1 ORDER BY ST_GeometryType(geometry)`, dbschemaProduction, table), id) + rows, err := s.db.Query(fmt.Sprintf(`SELECT osm_id, ST_AsText(geometry), tags FROM "%s"."%s" WHERE osm_id=$1 ORDER BY ST_GeometryType(geometry)`, s.dbschemaProduction(), table), id) if err != nil { t.Fatal(err) } @@ -295,7 +294,7 @@ func (s *importTestSuite) queryRowsTags(t *testing.T, table string, id int64) [] } func (s *importTestSuite) queryGeom(t *testing.T, table string, id int64) *geos.Geom { - stmt := fmt.Sprintf(`SELECT osm_id, ST_AsText(geometry) FROM "%s"."%s" WHERE osm_id=$1`, dbschemaProduction, table) + stmt := fmt.Sprintf(`SELECT osm_id, ST_AsText(geometry) FROM "%s"."%s" WHERE osm_id=$1`, s.dbschemaProduction(), table) row := s.db.QueryRow(stmt, id) r := record{} if err := row.Scan(&r.id, &r.wkt); err != nil { @@ -315,7 +314,7 @@ func (s *importTestSuite) queryGeom(t *testing.T, table string, id int64) *geos. } func (s *importTestSuite) queryDynamic(t *testing.T, table, where string) []map[string]string { - stmt := fmt.Sprintf(`SELECT hstore(r) FROM (SELECT ST_AsText(geometry) AS wkt, * FROM "%s"."%s" WHERE %s) AS r`, dbschemaProduction, table, where) + stmt := fmt.Sprintf(`SELECT hstore(r) FROM (SELECT ST_AsText(geometry) AS wkt, * FROM "%s"."%s" WHERE %s) AS r`, s.dbschemaProduction(), table, where) rows, err := s.db.Query(stmt) if err != nil { t.Fatal(err) @@ -344,7 +343,7 @@ type checkElem struct { tags map[string]string } -func assertRecords(t *testing.T, elems []checkElem) { +func (ts *importTestSuite) assertRecords(t *testing.T, elems []checkElem) { for _, e := range elems { keys := make([]string, 0, len(e.tags)) for k, _ := range e.tags { @@ -368,7 +367,7 @@ func assertRecords(t *testing.T, elems []checkElem) { } } -func assertHstore(t *testing.T, elems []checkElem) { +func (ts *importTestSuite) assertHstore(t *testing.T, elems []checkElem) { for _, e := range elems { r := ts.queryTags(t, e.table, e.id) if e.osmType == "" { @@ -388,14 +387,14 @@ func assertHstore(t *testing.T, elems []checkElem) { } } -func assertGeomValid(t *testing.T, e checkElem) { +func (ts *importTestSuite) assertGeomValid(t *testing.T, e checkElem) { geom := ts.queryGeom(t, e.table, e.id) if !ts.g.IsValid(geom) { t.Fatalf("geometry of %d is invalid", e.id) } } -func assertGeomArea(t *testing.T, e checkElem, expect float64) { +func (ts *importTestSuite) assertGeomArea(t *testing.T, e checkElem, expect float64) { geom := ts.queryGeom(t, e.table, e.id) if !ts.g.IsValid(geom) { t.Fatalf("geometry of %d is invalid", e.id) @@ -406,7 +405,7 @@ func assertGeomArea(t *testing.T, e checkElem, expect float64) { } } -func assertGeomLength(t *testing.T, e checkElem, expect float64) { +func (ts *importTestSuite) assertGeomLength(t *testing.T, e checkElem, expect float64) { geom := ts.queryGeom(t, e.table, e.id) if !ts.g.IsValid(geom) { t.Fatalf("geometry of %d is invalid", e.id) @@ -417,14 +416,14 @@ func assertGeomLength(t *testing.T, e checkElem, expect float64) { } } -func assertGeomType(t *testing.T, e checkElem, expect string) { +func (ts *importTestSuite) assertGeomType(t *testing.T, e checkElem, expect string) { actual := ts.g.Type(ts.queryGeom(t, e.table, e.id)) if actual != expect { t.Errorf("expected %s geometry for %d, got %s", expect, e.id, actual) } } -func assertCachedWay(t *testing.T, c *cache.OSMCache, id int64) *element.Way { +func (ts *importTestSuite) assertCachedWay(t *testing.T, c *cache.OSMCache, id int64) *element.Way { way, err := c.Ways.GetWay(id) if err == cache.NotFound { t.Errorf("missing way %d", id) @@ -437,7 +436,7 @@ func assertCachedWay(t *testing.T, c *cache.OSMCache, id int64) *element.Way { return way } -func assertCachedNode(t *testing.T, c *cache.OSMCache, id int64) *element.Node { +func (ts *importTestSuite) assertCachedNode(t *testing.T, c *cache.OSMCache, id int64) *element.Node { node, err := c.Nodes.GetNode(id) if err == cache.NotFound { node, err = c.Coords.GetCoord(id) diff --git a/test/route_relation_test.go b/test/route_relation_test.go index d2e0669..1f2ef9d 100644 --- a/test/route_relation_test.go +++ b/test/route_relation_test.go @@ -10,158 +10,168 @@ import ( "github.com/omniscale/imposm3/geom/geos" ) -func TestRouteRelation_Prepare(t *testing.T) { - var err error +func TestRouteRelation(t *testing.T) { + if testing.Short() { + t.Skip("system test skipped with -test.short") + } - ts.dir, err = ioutil.TempDir("", "imposm_test") - if err != nil { - t.Fatal(err) + ts := importTestSuite{ + name: "route_relation", } - ts.config = importConfig{ - connection: "postgis://", - cacheDir: ts.dir, - osmFileName: "build/route_relation.pbf", - mappingFileName: "route_relation_mapping.yml", - } - ts.g = geos.NewGeos() - ts.db, err = sql.Open("postgres", "sslmode=disable") - if err != nil { - t.Fatal(err) - } - ts.dropSchemas() -} - -func TestRouteRelation_Import(t *testing.T) { - if ts.tableExists(t, dbschemaImport, "osm_routes") != false { - t.Fatalf("table osm_routes exists in schema %s", dbschemaImport) - } - ts.importOsm(t) - if ts.tableExists(t, dbschemaImport, "osm_routes") != true { - t.Fatalf("table osm_routes does not exists in schema %s", dbschemaImport) - } -} - -func TestRouteRelation_Deploy(t *testing.T) { - ts.deployOsm(t) - if ts.tableExists(t, dbschemaImport, "osm_routes") != false { - t.Fatalf("table osm_routes exists in schema %s", dbschemaImport) - } - if ts.tableExists(t, dbschemaProduction, "osm_routes") != true { - t.Fatalf("table osm_routes does not exists in schema %s", dbschemaProduction) - } -} - -func TestRouteRelation_RelationData(t *testing.T) { - // check tags of relation - r := ts.queryTags(t, "osm_routes", -100901) - if r.tags["name"] != "Bus 301: A => B" { - t.Error(r) - } - - // check tags of master relation - r = ts.queryTags(t, "osm_routes", -100911) - if r.tags["name"] != "Bus 301" { - t.Error(r) - } -} - -func TestRouteRelation_MemberUpdatedByNode1(t *testing.T) { - // check that member is updated after node was modified - rows := ts.queryDynamic(t, "osm_route_members", "osm_id = -110901 AND member = 110101") - if len(rows) != 1 { - t.Fatal(rows) - } - if rows[0]["name"] != "Stop" { - t.Error(rows[0]) - } -} - -func TestRouteRelation_MemberGeomUpdated1(t *testing.T) { - rows := ts.queryDynamic(t, "osm_route_members", "osm_id = -100902 AND member = 100502") - if len(rows) != 1 { - t.Fatal(rows) - } - g := ts.g.FromWkt(rows[0]["wkt"]) - if math.Abs(g.Length()-111.32448543701321) > 0.00000001 { - t.Fatal(g.Length()) - } - - rows = ts.queryDynamic(t, "osm_route_members", "osm_id = -100902 AND member = 100503") - if len(rows) != 1 { - t.Fatal(rows) - } - if rows[0]["name"] != "" { - t.Error(rows[0]) - } -} - -func TestRouteRelation_NoRouteWithMissingMember(t *testing.T) { - // current implementation: route members are all or nothing. - // if one member is missing, no member is imported - if r := ts.queryDynamic(t, "osm_route_members", "osm_id = -120901 AND member = 120101"); len(r) > 0 { - t.Error("found member from route with missing members") - } -} - -// ####################################################################### - -func TestRouteRelation_Update(t *testing.T) { - ts.updateOsm(t, "./build/route_relation.osc.gz") -} - -// ####################################################################### - -func TestRouteRelation_MemberGeomUpdated2(t *testing.T) { - rows := ts.queryDynamic(t, "osm_route_members", "osm_id = -100902 AND member = 100502") - if len(rows) != 1 { - t.Fatal(rows) - } - g := ts.g.FromWkt(rows[0]["wkt"]) - if math.Abs(g.Length()-184.97560221624542) > 0.00000001 { - t.Fatal(g.Length()) - } - - // tag from member is updated - rows = ts.queryDynamic(t, "osm_route_members", "osm_id = -100902 AND member = 100503") - if len(rows) != 1 { - t.Fatal(rows) - } - if rows[0]["name"] != "new name" { - t.Error(rows[0]) - } - - // member is removed - rows = ts.queryDynamic(t, "osm_route_members", "osm_id = -100902 AND member = 100512") - if len(rows) != 0 { - t.Fatal(rows) - } - - // role from member is updated - rows = ts.queryDynamic(t, "osm_route_members", "osm_id = -100902 AND member = 100102") - if len(rows) != 1 { - t.Fatal(rows) - } - if rows[0]["role"] != "halt" { - t.Error(rows[0]) - } - -} - -func TestRouteRelation_MemberUpdatedByNode2(t *testing.T) { - // check that member is updated after node was modified - rows := ts.queryDynamic(t, "osm_route_members", "osm_id = -110901 AND member = 110101") - if len(rows) != 1 { - t.Fatal(rows) - } - if rows[0]["name"] != "Stop2" { - t.Error(rows[0]) - } -} - -func TestRouteRelation_Cleanup(t *testing.T) { - ts.dropSchemas() - if err := os.RemoveAll(ts.dir); err != nil { - t.Error(err) - } + t.Run("Prepare", func(t *testing.T) { + var err error + + ts.dir, err = ioutil.TempDir("", "imposm_test") + if err != nil { + t.Fatal(err) + } + ts.config = importConfig{ + connection: "postgis://", + cacheDir: ts.dir, + osmFileName: "build/route_relation.pbf", + mappingFileName: "route_relation_mapping.yml", + } + ts.g = geos.NewGeos() + + ts.db, err = sql.Open("postgres", "sslmode=disable") + if err != nil { + t.Fatal(err) + } + ts.dropSchemas() + }) + + t.Run("Import", func(t *testing.T) { + if ts.tableExists(t, ts.dbschemaImport(), "osm_routes") != false { + t.Fatalf("table osm_routes exists in schema %s", ts.dbschemaImport()) + } + ts.importOsm(t) + if ts.tableExists(t, ts.dbschemaImport(), "osm_routes") != true { + t.Fatalf("table osm_routes does not exists in schema %s", ts.dbschemaImport()) + } + }) + + t.Run("Deploy", func(t *testing.T) { + ts.deployOsm(t) + if ts.tableExists(t, ts.dbschemaImport(), "osm_routes") != false { + t.Fatalf("table osm_routes exists in schema %s", ts.dbschemaImport()) + } + if ts.tableExists(t, ts.dbschemaProduction(), "osm_routes") != true { + t.Fatalf("table osm_routes does not exists in schema %s", ts.dbschemaProduction()) + } + }) + + t.Run("RelationData", func(t *testing.T) { + // check tags of relation + r := ts.queryTags(t, "osm_routes", -100901) + if r.tags["name"] != "Bus 301: A => B" { + t.Error(r) + } + + // check tags of master relation + r = ts.queryTags(t, "osm_routes", -100911) + if r.tags["name"] != "Bus 301" { + t.Error(r) + } + }) + + t.Run("MemberUpdatedByNode1", func(t *testing.T) { + // check that member is updated after node was modified + rows := ts.queryDynamic(t, "osm_route_members", "osm_id = -110901 AND member = 110101") + if len(rows) != 1 { + t.Fatal(rows) + } + if rows[0]["name"] != "Stop" { + t.Error(rows[0]) + } + }) + + t.Run("MemberGeomUpdated1", func(t *testing.T) { + rows := ts.queryDynamic(t, "osm_route_members", "osm_id = -100902 AND member = 100502") + if len(rows) != 1 { + t.Fatal(rows) + } + g := ts.g.FromWkt(rows[0]["wkt"]) + if math.Abs(g.Length()-111.32448543701321) > 0.00000001 { + t.Fatal(g.Length()) + } + + rows = ts.queryDynamic(t, "osm_route_members", "osm_id = -100902 AND member = 100503") + if len(rows) != 1 { + t.Fatal(rows) + } + if rows[0]["name"] != "" { + t.Error(rows[0]) + } + }) + + t.Run("NoRouteWithMissingMember", func(t *testing.T) { + // current implementation: route members are all or nothing. + // if one member is missing, no member is imported + if r := ts.queryDynamic(t, "osm_route_members", "osm_id = -120901 AND member = 120101"); len(r) > 0 { + t.Error("found member from route with missing members") + } + }) + + // ####################################################################### + + t.Run("Update", func(t *testing.T) { + ts.updateOsm(t, "build/route_relation.osc.gz") + }) + + // ####################################################################### + + t.Run("MemberGeomUpdated2", func(t *testing.T) { + rows := ts.queryDynamic(t, "osm_route_members", "osm_id = -100902 AND member = 100502") + if len(rows) != 1 { + t.Fatal(rows) + } + g := ts.g.FromWkt(rows[0]["wkt"]) + if math.Abs(g.Length()-184.97560221624542) > 0.00000001 { + t.Fatal(g.Length()) + } + + // tag from member is updated + rows = ts.queryDynamic(t, "osm_route_members", "osm_id = -100902 AND member = 100503") + if len(rows) != 1 { + t.Fatal(rows) + } + if rows[0]["name"] != "new name" { + t.Error(rows[0]) + } + + // member is removed + rows = ts.queryDynamic(t, "osm_route_members", "osm_id = -100902 AND member = 100512") + if len(rows) != 0 { + t.Fatal(rows) + } + + // role from member is updated + rows = ts.queryDynamic(t, "osm_route_members", "osm_id = -100902 AND member = 100102") + if len(rows) != 1 { + t.Fatal(rows) + } + if rows[0]["role"] != "halt" { + t.Error(rows[0]) + } + + }) + + t.Run("MemberUpdatedByNode2", func(t *testing.T) { + // check that member is updated after node was modified + rows := ts.queryDynamic(t, "osm_route_members", "osm_id = -110901 AND member = 110101") + if len(rows) != 1 { + t.Fatal(rows) + } + if rows[0]["name"] != "Stop2" { + t.Error(rows[0]) + } + }) + + t.Run("Cleanup", func(t *testing.T) { + ts.dropSchemas() + if err := os.RemoveAll(ts.dir); err != nil { + t.Error(err) + } + }) } diff --git a/test/single_table_test.go b/test/single_table_test.go index b34dbac..9760ddd 100644 --- a/test/single_table_test.go +++ b/test/single_table_test.go @@ -13,195 +13,205 @@ import ( const RelOffset = -1e17 -func TestSingleTable_Prepare(t *testing.T) { - var err error - - ts.dir, err = ioutil.TempDir("", "imposm_test") - if err != nil { - t.Fatal(err) - } - ts.config = importConfig{ - connection: "postgis://", - cacheDir: ts.dir, - osmFileName: "build/single_table.pbf", - mappingFileName: "single_table_mapping.json", - } - ts.g = geos.NewGeos() - - ts.db, err = sql.Open("postgres", "sslmode=disable") - if err != nil { - t.Fatal(err) - } - ts.dropSchemas() -} - -func TestSingleTable_Import(t *testing.T) { - if ts.tableExists(t, dbschemaImport, "osm_all") != false { - t.Fatalf("table osm_all exists in schema %s", dbschemaImport) - } - ts.importOsm(t) - if ts.tableExists(t, dbschemaImport, "osm_all") != true { - t.Fatalf("table osm_all does not exists in schema %s", dbschemaImport) - } -} - -func TestSingleTable_Deploy(t *testing.T) { - ts.deployOsm(t) - if ts.tableExists(t, dbschemaImport, "osm_all") != false { - t.Fatalf("table osm_all exists in schema %s", dbschemaImport) - } - if ts.tableExists(t, dbschemaProduction, "osm_all") != true { - t.Fatalf("table osm_all does not exists in schema %s", dbschemaProduction) - } -} - -func TestSingleTable_NonMappedNodeIsMissing(t *testing.T) { - // Node without mapped tags is missing. - cache := ts.cache(t) - defer cache.Close() - assertCachedNode(t, cache, 10001) - - assertHstore(t, []checkElem{ - {"osm_all", 10001, Missing, nil}, - }) -} - -func TestSingleTable_MappedNode(t *testing.T) { - // Node is stored with all tags. - cache := ts.cache(t) - defer cache.Close() - assertCachedNode(t, cache, 10002) - - assertHstore(t, []checkElem{ - {"osm_all", 10002, "*", map[string]string{"random": "tag", "but": "mapped", "poi": "unicorn"}}, - }) -} - -func TestSingleTable_NonMappedWayIsMissing(t *testing.T) { - // Way without mapped tags is missing. - cache := ts.cache(t) - defer cache.Close() - assertCachedWay(t, cache, 20101) - assertCachedWay(t, cache, 20102) - assertCachedWay(t, cache, 20103) - - assertHstore(t, []checkElem{ - {"osm_all", 20101, Missing, nil}, - {"osm_all", 20102, Missing, nil}, - {"osm_all", 20103, Missing, nil}, - }) -} - -func TestSingleTable_MappedWay(t *testing.T) { - // Way is stored with all tags. - cache := ts.cache(t) - defer cache.Close() - assertCachedWay(t, cache, 20201) - - assertHstore(t, []checkElem{ - {"osm_all", -20201, "*", map[string]string{"random": "tag", "highway": "yes"}}, - }) -} - -func TestSingleTable_NonMappedClosedWayIsMissing(t *testing.T) { - // Closed way without mapped tags is missing. - cache := ts.cache(t) - defer cache.Close() - assertCachedWay(t, cache, 20301) - assertHstore(t, []checkElem{ - {"osm_all", 20301, Missing, nil}, - {"osm_all", -20301, Missing, nil}, - }) -} - -func TestSingleTable_MappedClosedWay(t *testing.T) { - // Closed way is stored with all tags. - assertHstore(t, []checkElem{ - {"osm_all", -20401, "*", map[string]string{"random": "tag", "building": "yes"}}, - }) -} - -func TestSingleTable_MappedClosedWayAreaYes(t *testing.T) { - // Closed way with area=yes is not stored as linestring. - assertHstore(t, []checkElem{ - {"osm_all", -20501, "*", map[string]string{"random": "tag", "landuse": "grass", "highway": "pedestrian", "area": "yes"}}, - }) - assertGeomType(t, checkElem{"osm_all", -20501, "*", nil}, "Polygon") -} - -func TestSingleTable_MappedClosedWayAreaNo(t *testing.T) { - // Closed way with area=no is not stored as polygon. - assertHstore(t, []checkElem{ - {"osm_all", -20502, "*", map[string]string{"random": "tag", "landuse": "grass", "highway": "pedestrian", "area": "no"}}, - }) - assertGeomType(t, checkElem{"osm_all", -20502, "*", nil}, "LineString") -} - -func TestSingleTable_MappedClosedWayWithoutArea(t *testing.T) { - // Closed way without area is stored as mapped (linestring and polygon). - - rows := ts.queryRowsTags(t, "osm_all", -20601) - if len(rows) != 2 || strings.HasPrefix(rows[0].wkt, "LineString") || strings.HasPrefix(rows[1].wkt, "Polygon") { - t.Errorf("unexpected geometries: %v", rows) - } -} - -func TestSingleTable_DuplicateIds1(t *testing.T) { - // Points/lines/polygons with same ID are inserted. - - assertHstore(t, []checkElem{ - {"osm_all", 31101, "*", map[string]string{"amenity": "cafe"}}, - }) - - rows := ts.queryRowsTags(t, "osm_all", -31101) - if len(rows) != 2 || strings.HasPrefix(rows[0].wkt, "LineString") || strings.HasPrefix(rows[1].wkt, "Polygon") { - t.Errorf("unexpected geometries: %v", rows) +func TestSingleTable(t *testing.T) { + if testing.Short() { + t.Skip("system test skipped with -test.short") } - assertHstore(t, []checkElem{ - {"osm_all", RelOffset - 31101, "*", map[string]string{"building": "yes", "type": "multipolygon"}}, - }) - assertGeomType(t, checkElem{"osm_all", RelOffset - 31101, "*", nil}, "Polygon") -} - -// ####################################################################### - -func TestSingleTable_Update(t *testing.T) { - ts.updateOsm(t, "./build/single_table.osc.gz") -} - -// ####################################################################### - -func TestSingleTable_DuplicateIds2(t *testing.T) { - // Node moved and ways/rels with same ID are still present. - - assertHstore(t, []checkElem{ - {"osm_all", 31101, "*", map[string]string{"amenity": "cafe"}}, - }) - - rows := ts.queryRowsTags(t, "osm_all", -31101) - if len(rows) != 2 || strings.HasPrefix(rows[0].wkt, "LineString") || strings.HasPrefix(rows[1].wkt, "Polygon") { - t.Errorf("unexpected geometries: %v", rows) + ts := importTestSuite{ + name: "single_table", } - assertHstore(t, []checkElem{ - {"osm_all", RelOffset - 31101, "*", map[string]string{"building": "yes", "type": "multipolygon"}}, + t.Run("Prepare", func(t *testing.T) { + var err error + + ts.dir, err = ioutil.TempDir("", "imposm_test") + if err != nil { + t.Fatal(err) + } + ts.config = importConfig{ + connection: "postgis://", + cacheDir: ts.dir, + osmFileName: "build/single_table.pbf", + mappingFileName: "single_table_mapping.json", + } + ts.g = geos.NewGeos() + + ts.db, err = sql.Open("postgres", "sslmode=disable") + if err != nil { + t.Fatal(err) + } + ts.dropSchemas() }) - assertGeomType(t, checkElem{"osm_all", RelOffset - 31101, "*", nil}, "Polygon") -} -func TestSingleTable_ModifiedRelation2(t *testing.T) { - // Modified relation is not inserted twice. Check for #88 + t.Run("Import", func(t *testing.T) { + if ts.tableExists(t, ts.dbschemaImport(), "osm_all") != false { + t.Fatalf("table osm_all exists in schema %s", ts.dbschemaImport()) + } + ts.importOsm(t) + if ts.tableExists(t, ts.dbschemaImport(), "osm_all") != true { + t.Fatalf("table osm_all does not exists in schema %s", ts.dbschemaImport()) + } + }) - rows := ts.queryRowsTags(t, "osm_all", RelOffset-32901) - if len(rows) != 1 { - t.Errorf("found duplicate row: %v", rows) - } -} + t.Run("Deploy", func(t *testing.T) { + ts.deployOsm(t) + if ts.tableExists(t, ts.dbschemaImport(), "osm_all") != false { + t.Fatalf("table osm_all exists in schema %s", ts.dbschemaImport()) + } + if ts.tableExists(t, ts.dbschemaProduction(), "osm_all") != true { + t.Fatalf("table osm_all does not exists in schema %s", ts.dbschemaProduction()) + } + }) -func TestSingleTable_Cleanup(t *testing.T) { - ts.dropSchemas() - if err := os.RemoveAll(ts.dir); err != nil { - t.Error(err) - } + t.Run("NonMappedNodeIsMissing", func(t *testing.T) { + // Node without mapped tags is missing. + cache := ts.cache(t) + defer cache.Close() + ts.assertCachedNode(t, cache, 10001) + + ts.assertHstore(t, []checkElem{ + {"osm_all", 10001, Missing, nil}, + }) + }) + + t.Run("MappedNode", func(t *testing.T) { + // Node is stored with all tags. + cache := ts.cache(t) + defer cache.Close() + ts.assertCachedNode(t, cache, 10002) + + ts.assertHstore(t, []checkElem{ + {"osm_all", 10002, "*", map[string]string{"random": "tag", "but": "mapped", "poi": "unicorn"}}, + }) + }) + + t.Run("NonMappedWayIsMissing", func(t *testing.T) { + // Way without mapped tags is missing. + cache := ts.cache(t) + defer cache.Close() + ts.assertCachedWay(t, cache, 20101) + ts.assertCachedWay(t, cache, 20102) + ts.assertCachedWay(t, cache, 20103) + + ts.assertHstore(t, []checkElem{ + {"osm_all", 20101, Missing, nil}, + {"osm_all", 20102, Missing, nil}, + {"osm_all", 20103, Missing, nil}, + }) + }) + + t.Run("MappedWay", func(t *testing.T) { + // Way is stored with all tags. + cache := ts.cache(t) + defer cache.Close() + ts.assertCachedWay(t, cache, 20201) + + ts.assertHstore(t, []checkElem{ + {"osm_all", -20201, "*", map[string]string{"random": "tag", "highway": "yes"}}, + }) + }) + + t.Run("NonMappedClosedWayIsMissing", func(t *testing.T) { + // Closed way without mapped tags is missing. + cache := ts.cache(t) + defer cache.Close() + ts.assertCachedWay(t, cache, 20301) + ts.assertHstore(t, []checkElem{ + {"osm_all", 20301, Missing, nil}, + {"osm_all", -20301, Missing, nil}, + }) + }) + + t.Run("MappedClosedWay", func(t *testing.T) { + // Closed way is stored with all tags. + ts.assertHstore(t, []checkElem{ + {"osm_all", -20401, "*", map[string]string{"random": "tag", "building": "yes"}}, + }) + }) + + t.Run("MappedClosedWayAreaYes", func(t *testing.T) { + // Closed way with area=yes is not stored as linestring. + ts.assertHstore(t, []checkElem{ + {"osm_all", -20501, "*", map[string]string{"random": "tag", "landuse": "grass", "highway": "pedestrian", "area": "yes"}}, + }) + ts.assertGeomType(t, checkElem{"osm_all", -20501, "*", nil}, "Polygon") + }) + + t.Run("MappedClosedWayAreaNo", func(t *testing.T) { + // Closed way with area=no is not stored as polygon. + ts.assertHstore(t, []checkElem{ + {"osm_all", -20502, "*", map[string]string{"random": "tag", "landuse": "grass", "highway": "pedestrian", "area": "no"}}, + }) + ts.assertGeomType(t, checkElem{"osm_all", -20502, "*", nil}, "LineString") + }) + + t.Run("MappedClosedWayWithoutArea", func(t *testing.T) { + // Closed way without area is stored as mapped (linestring and polygon). + + rows := ts.queryRowsTags(t, "osm_all", -20601) + if len(rows) != 2 || strings.HasPrefix(rows[0].wkt, "LineString") || strings.HasPrefix(rows[1].wkt, "Polygon") { + t.Errorf("unexpected geometries: %v", rows) + } + }) + + t.Run("DuplicateIds1", func(t *testing.T) { + // Points/lines/polygons with same ID are inserted. + + ts.assertHstore(t, []checkElem{ + {"osm_all", 31101, "*", map[string]string{"amenity": "cafe"}}, + }) + + rows := ts.queryRowsTags(t, "osm_all", -31101) + if len(rows) != 2 || strings.HasPrefix(rows[0].wkt, "LineString") || strings.HasPrefix(rows[1].wkt, "Polygon") { + t.Errorf("unexpected geometries: %v", rows) + } + + ts.assertHstore(t, []checkElem{ + {"osm_all", RelOffset - 31101, "*", map[string]string{"building": "yes", "type": "multipolygon"}}, + }) + ts.assertGeomType(t, checkElem{"osm_all", RelOffset - 31101, "*", nil}, "Polygon") + }) + + // ####################################################################### + + t.Run("Update", func(t *testing.T) { + ts.updateOsm(t, "build/single_table.osc.gz") + }) + + // ####################################################################### + + t.Run("DuplicateIds2", func(t *testing.T) { + // Node moved and ways/rels with same ID are still present. + + ts.assertHstore(t, []checkElem{ + {"osm_all", 31101, "*", map[string]string{"amenity": "cafe"}}, + }) + + rows := ts.queryRowsTags(t, "osm_all", -31101) + if len(rows) != 2 || strings.HasPrefix(rows[0].wkt, "LineString") || strings.HasPrefix(rows[1].wkt, "Polygon") { + t.Errorf("unexpected geometries: %v", rows) + } + + ts.assertHstore(t, []checkElem{ + {"osm_all", RelOffset - 31101, "*", map[string]string{"building": "yes", "type": "multipolygon"}}, + }) + ts.assertGeomType(t, checkElem{"osm_all", RelOffset - 31101, "*", nil}, "Polygon") + }) + + t.Run("ModifiedRelation2", func(t *testing.T) { + // Modified relation is not inserted twice. Check for #88 + + rows := ts.queryRowsTags(t, "osm_all", RelOffset-32901) + if len(rows) != 1 { + t.Errorf("found duplicate row: %v", rows) + } + }) + + t.Run("Cleanup", func(t *testing.T) { + ts.dropSchemas() + if err := os.RemoveAll(ts.dir); err != nil { + t.Error(err) + } + }) }