Skip to content

Commit

Permalink
Add tests to make sure no schema except specified one is touched
Browse files Browse the repository at this point in the history
  • Loading branch information
falko17 committed Oct 3, 2024
1 parent a3a21a2 commit 4eb9097
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 54 deletions.
7 changes: 7 additions & 0 deletions src/pgsql-params.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ class connection_params_t

auto end() const noexcept { return m_params.end(); }

void merge_with(connection_params_t const &other)
{
for (auto const &p : other.m_params) {
m_params[p.first] = p.second;
}
}

private:
std::map<std::string, std::string> m_params;

Expand Down
4 changes: 2 additions & 2 deletions tests/common-import.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class import_t
std::initializer_list<std::string> input_data,
std::string const &format = "opl")
{
options.connection_params = m_db.connection_params();
options.connection_params.merge_with(m_db.connection_params());

properties_t const properties{options.connection_params,
options.middle_dbschema};
Expand Down Expand Up @@ -165,7 +165,7 @@ class import_t

void run_file(options_t options, char const *file = nullptr)
{
options.connection_params = m_db.connection_params();
options.connection_params.merge_with(m_db.connection_params());

properties_t const properties{options.connection_params,
options.middle_dbschema};
Expand Down
15 changes: 15 additions & 0 deletions tests/common-options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,21 @@ class opt_t
return *this;
}

opt_t &schema(char const *schema_name)
{
m_opt.dbschema = schema_name;
m_opt.middle_dbschema = schema_name;
m_opt.output_dbschema = schema_name;
return *this;
}

opt_t &user(char const *user, char const *password)
{
m_opt.connection_params.set("user", user);
m_opt.connection_params.set("password", password);
return *this;
}

private:
options_t m_opt;
};
Expand Down
155 changes: 103 additions & 52 deletions tests/test-output-flex-update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "common-import.hpp"
#include "common-options.hpp"
#include "common-pg.hpp"

namespace {

Expand Down Expand Up @@ -38,8 +39,50 @@ struct options_slim_expire
}
};

struct options_slim_schema
{
static options_t options()
{
auto conn = db.db().connect();
// Create limited user (if it doesn't exist yet),
// which we need to test that the public schema won't be touched.
// If the public schema is tried to be modified at any point, this user won't have the
// necessary permissions, and hence the test will fail.
conn.exec(R"(
DO
$$
BEGIN
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'limited') THEN
CREATE ROLE limited LOGIN PASSWORD 'password_limited';
END IF;
END
$$;
)");
conn.exec("REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM "
"PUBLIC, limited;");
conn.exec("REVOKE CREATE ON SCHEMA public FROM PUBLIC, limited;");
conn.exec(
"CREATE SCHEMA IF NOT EXISTS myschema AUTHORIZATION limited;");
conn.close();
return testing::opt_t()
.slim()
.flex(conf_file)
.schema("myschema")
.user("limited", "password_limited");
}
};

// Return a string with the schema name prepended to the table name.
std::string with_schema(char const *table_name, options_t const &options)
{
if (options.dbschema.empty()) {
return std::string(table_name);
}
return options.dbschema + "." + table_name;
}

TEMPLATE_TEST_CASE("updating a node", "", options_slim_default,
options_slim_expire)
options_slim_expire, options_slim_schema)
{
options_t options = TestType::options();

Expand All @@ -48,16 +91,16 @@ TEMPLATE_TEST_CASE("updating a node", "", options_slim_default,

auto conn = db.db().connect();

REQUIRE(0 == conn.get_count("osm2pgsql_test_point"));
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_point", options)));

// give the node a tag...
options.append = true;
REQUIRE_NOTHROW(
db.run_import(options, "n10 v2 dV x10 y10 Tamenity=restaurant\n"));

REQUIRE(1 == conn.get_count("osm2pgsql_test_point"));
REQUIRE(1 == conn.get_count(with_schema("osm2pgsql_test_point", options)));
REQUIRE(1 ==
conn.get_count("osm2pgsql_test_point",
conn.get_count(with_schema("osm2pgsql_test_point", options),
"node_id = 10 AND tags->'amenity' = 'restaurant'"));

SECTION("remove the tag from node")
Expand All @@ -70,11 +113,11 @@ TEMPLATE_TEST_CASE("updating a node", "", options_slim_default,
REQUIRE_NOTHROW(db.run_import(options, "n10 v3 dD\n"));
}

REQUIRE(0 == conn.get_count("osm2pgsql_test_point"));
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_point", options)));
}

TEMPLATE_TEST_CASE("updating a way", "", options_slim_default,
options_slim_expire)
options_slim_expire, options_slim_schema)
{
options_t options = TestType::options();

Expand All @@ -86,9 +129,9 @@ TEMPLATE_TEST_CASE("updating a way", "", options_slim_default,

auto conn = db.db().connect();

REQUIRE(0 == conn.get_count("osm2pgsql_test_point"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_line"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_line",
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_point", options)));
REQUIRE(1 == conn.get_count(with_schema("osm2pgsql_test_line", options)));
REQUIRE(1 == conn.get_count(with_schema("osm2pgsql_test_line", options),
"osm_id = 20 AND tags->'highway' = 'primary' "
"AND ST_NumPoints(geom) = 2"));

Expand All @@ -97,18 +140,18 @@ TEMPLATE_TEST_CASE("updating a way", "", options_slim_default,
REQUIRE_NOTHROW(
db.run_import(options, "w20 v2 dV Thighway=secondary Nn10,n11\n"));

REQUIRE(0 == conn.get_count("osm2pgsql_test_point"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_line"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_line",
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_point", options)));
REQUIRE(1 == conn.get_count(with_schema("osm2pgsql_test_line", options)));
REQUIRE(1 == conn.get_count(with_schema("osm2pgsql_test_line", options),
"osm_id = 20 AND tags->'highway' = "
"'secondary' AND ST_NumPoints(geom) = 2"));

// now change a node in the way...
REQUIRE_NOTHROW(db.run_import(options, "n10 v2 dV x10.0 y10.3\n"));

REQUIRE(0 == conn.get_count("osm2pgsql_test_point"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_line"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_line",
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_point", options)));
REQUIRE(1 == conn.get_count(with_schema("osm2pgsql_test_line", options)));
REQUIRE(1 == conn.get_count(with_schema("osm2pgsql_test_line", options),
"osm_id = 20 AND tags->'highway' = "
"'secondary' AND ST_NumPoints(geom) = 2"));

Expand All @@ -117,21 +160,21 @@ TEMPLATE_TEST_CASE("updating a way", "", options_slim_default,
options, "n12 v1 dV x10.2 y10.1\n"
"w20 v3 dV Thighway=residential Nn10,n11,n12\n"));

REQUIRE(0 == conn.get_count("osm2pgsql_test_point"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_line"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_line",
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_point", options)));
REQUIRE(1 == conn.get_count(with_schema("osm2pgsql_test_line", options)));
REQUIRE(1 == conn.get_count(with_schema("osm2pgsql_test_line", options),
"osm_id = 20 AND tags->'highway' = "
"'residential' AND ST_NumPoints(geom) = 3"));

// now delete the way...
REQUIRE_NOTHROW(db.run_import(options, "w20 v4 dD\n"));

REQUIRE(0 == conn.get_count("osm2pgsql_test_point"));
REQUIRE(0 == conn.get_count("osm2pgsql_test_line"));
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_point", options)));
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_line", options)));
}

TEMPLATE_TEST_CASE("ways as linestrings and polygons", "", options_slim_default,
options_slim_expire)
options_slim_expire, options_slim_schema)
{
options_t options = TestType::options();

Expand All @@ -145,10 +188,11 @@ TEMPLATE_TEST_CASE("ways as linestrings and polygons", "", options_slim_default,

auto conn = db.db().connect();

REQUIRE(0 == conn.get_count("osm2pgsql_test_point"));
REQUIRE(0 == conn.get_count("osm2pgsql_test_line"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_polygon"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_polygon",
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_point", options)));
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_line", options)));
REQUIRE(1 ==
conn.get_count(with_schema("osm2pgsql_test_polygon", options)));
REQUIRE(1 == conn.get_count(with_schema("osm2pgsql_test_polygon", options),
"osm_id = 20 AND tags->'building' = 'yes' AND "
"ST_GeometryType(geom) = 'ST_Polygon'"));

Expand All @@ -157,48 +201,52 @@ TEMPLATE_TEST_CASE("ways as linestrings and polygons", "", options_slim_default,
REQUIRE_NOTHROW(db.run_import(
options, "w20 v2 dV Thighway=secondary Nn10,n11,n12,n13,n10\n"));

REQUIRE(0 == conn.get_count("osm2pgsql_test_point"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_line"));
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_point", options)));
REQUIRE(1 == conn.get_count(with_schema("osm2pgsql_test_line", options)));
REQUIRE(1 ==
conn.get_count("osm2pgsql_test_line",
conn.get_count(with_schema("osm2pgsql_test_line", options),
"osm_id = 20 AND tags->'highway' = 'secondary' AND "
"ST_GeometryType(geom) = 'ST_LineString'"));
REQUIRE(0 == conn.get_count("osm2pgsql_test_polygon"));
REQUIRE(0 ==
conn.get_count(with_schema("osm2pgsql_test_polygon", options)));

// now remove a node from the way...
REQUIRE_NOTHROW(db.run_import(
options, "w20 v3 dV Thighway=secondary Nn10,n11,n12,n13\n"));

REQUIRE(0 == conn.get_count("osm2pgsql_test_point"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_line"));
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_point", options)));
REQUIRE(1 == conn.get_count(with_schema("osm2pgsql_test_line", options)));
REQUIRE(1 ==
conn.get_count("osm2pgsql_test_line",
conn.get_count(with_schema("osm2pgsql_test_line", options),
"osm_id = 20 AND tags->'highway' = 'secondary' AND "
"ST_GeometryType(geom) = 'ST_LineString'"));
REQUIRE(0 == conn.get_count("osm2pgsql_test_polygon"));
REQUIRE(0 ==
conn.get_count(with_schema("osm2pgsql_test_polygon", options)));

// now change the tag back to an area tag (but the way is not closed)...
REQUIRE_NOTHROW(
db.run_import(options, "w20 v4 dV Tbuilding=yes Nn10,n11,n12,n13\n"));

REQUIRE(0 == conn.get_count("osm2pgsql_test_point"));
REQUIRE(0 == conn.get_count("osm2pgsql_test_line"));
REQUIRE(0 == conn.get_count("osm2pgsql_test_polygon"));
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_point", options)));
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_line", options)));
REQUIRE(0 ==
conn.get_count(with_schema("osm2pgsql_test_polygon", options)));

// now close the way again
REQUIRE_NOTHROW(db.run_import(
options, "w20 v5 dV Tbuilding=yes Nn10,n11,n12,n13,n10\n"));

REQUIRE(0 == conn.get_count("osm2pgsql_test_point"));
REQUIRE(0 == conn.get_count("osm2pgsql_test_line"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_polygon"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_polygon",
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_point", options)));
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_line", options)));
REQUIRE(1 ==
conn.get_count(with_schema("osm2pgsql_test_polygon", options)));
REQUIRE(1 == conn.get_count(with_schema("osm2pgsql_test_polygon", options),
"osm_id = 20 AND tags->'building' = 'yes' AND "
"ST_GeometryType(geom) = 'ST_Polygon'"));
}

TEMPLATE_TEST_CASE("multipolygons", "", options_slim_default,
options_slim_expire)
options_slim_expire, options_slim_schema)
{
options_t options = TestType::options();

Expand All @@ -213,10 +261,11 @@ TEMPLATE_TEST_CASE("multipolygons", "", options_slim_default,

auto conn = db.db().connect();

REQUIRE(0 == conn.get_count("osm2pgsql_test_point"));
REQUIRE(0 == conn.get_count("osm2pgsql_test_line"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_polygon"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_polygon",
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_point", options)));
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_line", options)));
REQUIRE(1 ==
conn.get_count(with_schema("osm2pgsql_test_polygon", options)));
REQUIRE(1 == conn.get_count(with_schema("osm2pgsql_test_polygon", options),
"osm_id = -30 AND tags->'building' = 'yes' AND "
"ST_GeometryType(geom) = 'ST_Polygon'"));

Expand All @@ -226,10 +275,11 @@ TEMPLATE_TEST_CASE("multipolygons", "", options_slim_default,
options,
"r30 v2 dV Ttype=multipolygon,building=yes,name=Shed Mw20@\n"));

REQUIRE(0 == conn.get_count("osm2pgsql_test_point"));
REQUIRE(0 == conn.get_count("osm2pgsql_test_line"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_polygon"));
REQUIRE(1 == conn.get_count("osm2pgsql_test_polygon",
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_point", options)));
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_line", options)));
REQUIRE(1 ==
conn.get_count(with_schema("osm2pgsql_test_polygon", options)));
REQUIRE(1 == conn.get_count(with_schema("osm2pgsql_test_polygon", options),
"osm_id = -30 AND tags->'building' = 'yes' AND "
"ST_GeometryType(geom) = 'ST_Polygon'"));

Expand All @@ -244,7 +294,8 @@ TEMPLATE_TEST_CASE("multipolygons", "", options_slim_default,
options, "r30 v3 dV Tbuilding=yes,name=Shed Mw20@\n"));
}

REQUIRE(0 == conn.get_count("osm2pgsql_test_point"));
REQUIRE(0 == conn.get_count("osm2pgsql_test_line"));
REQUIRE(0 == conn.get_count("osm2pgsql_test_polygon"));
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_point", options)));
REQUIRE(0 == conn.get_count(with_schema("osm2pgsql_test_line", options)));
REQUIRE(0 ==
conn.get_count(with_schema("osm2pgsql_test_polygon", options)));
}

0 comments on commit 4eb9097

Please sign in to comment.