From 9ce2d6fc0e1d7591d0d588a16ab6589910092cfc Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 2 Jun 2021 22:51:31 +0200 Subject: Make proj_context_set_autoclose_database() a no-op as it would defeat the purpose of the new database connection sharing --- test/unit/test_c_api.cpp | 100 ----------------------------------------------- 1 file changed, 100 deletions(-) (limited to 'test/unit/test_c_api.cpp') diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp index 99d91e3b..d9e731a7 100644 --- a/test/unit/test_c_api.cpp +++ b/test/unit/test_c_api.cpp @@ -4287,106 +4287,6 @@ TEST_F(CApi, proj_as_projjson) { // --------------------------------------------------------------------------- -struct Fixture_proj_context_set_autoclose_database : public CApi { - void test(bool autoclose) { - proj_context_set_autoclose_database(m_ctxt, autoclose); - - auto c_path = proj_context_get_database_path(m_ctxt); - ASSERT_TRUE(c_path != nullptr); - std::string path(c_path); - - FILE *f = fopen(path.c_str(), "rb"); - ASSERT_NE(f, nullptr); - fseek(f, 0, SEEK_END); - auto length = ftell(f); - std::string content; - content.resize(static_cast(length)); - fseek(f, 0, SEEK_SET); - auto read_bytes = fread(&content[0], 1, content.size(), f); - ASSERT_EQ(read_bytes, content.size()); - fclose(f); - const char *tempdir = getenv("TEMP"); - if (!tempdir) { - tempdir = getenv("TMP"); - } - if (!tempdir) { - tempdir = "/tmp"; - } - std::string tmp_filename( - std::string(tempdir) + - "/test_proj_context_set_autoclose_database.db"); - f = fopen(tmp_filename.c_str(), "wb"); - if (!f) { - std::cerr << "Cannot create " << tmp_filename << std::endl; - return; - } - fwrite(content.data(), 1, content.size(), f); - fclose(f); - - { - sqlite3 *db = nullptr; - sqlite3_open_v2(tmp_filename.c_str(), &db, SQLITE_OPEN_READWRITE, - nullptr); - ASSERT_NE(db, nullptr); - ASSERT_TRUE(sqlite3_exec(db, - "UPDATE geodetic_crs SET name = 'foo' " - "WHERE auth_name = 'EPSG' and code = " - "'4326'", - nullptr, nullptr, nullptr) == SQLITE_OK); - sqlite3_close(db); - } - - EXPECT_TRUE(proj_context_set_database_path(m_ctxt, tmp_filename.c_str(), - nullptr, nullptr)); - { - auto crs = proj_create_from_database( - m_ctxt, "EPSG", "4326", PJ_CATEGORY_CRS, false, nullptr); - ObjectKeeper keeper(crs); - ASSERT_NE(crs, nullptr); - EXPECT_EQ(proj_get_name(crs), std::string("foo")); - } - - { - sqlite3 *db = nullptr; - sqlite3_open_v2(tmp_filename.c_str(), &db, SQLITE_OPEN_READWRITE, - nullptr); - ASSERT_NE(db, nullptr); - ASSERT_TRUE(sqlite3_exec(db, - "UPDATE geodetic_crs SET name = 'bar' " - "WHERE auth_name = 'EPSG' and code = " - "'4326'", - nullptr, nullptr, nullptr) == SQLITE_OK); - sqlite3_close(db); - } - { - auto crs = proj_create_from_database( - m_ctxt, "EPSG", "4326", PJ_CATEGORY_CRS, false, nullptr); - ObjectKeeper keeper(crs); - ASSERT_NE(crs, nullptr); - EXPECT_EQ(proj_get_name(crs), - std::string(autoclose ? "bar" : "foo")); - } - - if (!autoclose) { - proj_context_destroy(m_ctxt); - m_ctxt = nullptr; - } - std::remove(tmp_filename.c_str()); - } -}; - -TEST_F(Fixture_proj_context_set_autoclose_database, - proj_context_set_autoclose_database_true) { - test(true); -} - -TEST_F(Fixture_proj_context_set_autoclose_database, - proj_context_set_autoclose_database_false) { - test(false); -} - -// --------------------------------------------------------------------------- - TEST_F(CApi, proj_context_copy_from_default) { auto c_path = proj_context_get_database_path(m_ctxt); ASSERT_TRUE(c_path != nullptr); -- cgit v1.2.3 From 1c80b05e007340ed213e7f492b73631810e8aec4 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 2 Jun 2021 23:11:31 +0200 Subject: Check that database connection sharing properly works --- test/unit/test_c_api.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) (limited to 'test/unit/test_c_api.cpp') diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp index d9e731a7..90641bd1 100644 --- a/test/unit/test_c_api.cpp +++ b/test/unit/test_c_api.cpp @@ -47,6 +47,10 @@ #include +#ifndef __MINGW32__ +#include +#endif + using namespace osgeo::proj::common; using namespace osgeo::proj::crs; using namespace osgeo::proj::cs; @@ -5544,4 +5548,72 @@ TEST_F(CApi, proj_get_geoid_models_from_database) { EXPECT_FALSE(findInList(list, "OSGM15")); } +// --------------------------------------------------------------------------- + +#if !defined(_WIN32) +TEST_F(CApi, open_plenty_of_contexts) { + // Test that we only consume 1 file handle for the connection to the + // database + std::vector dummyFilePointers; + std::vector ctxts; + // 1024 is the number of file descriptors that can be opened simultaneously + // by a Linux process (by default) + for (int i = 0; i < 1024 - 50; i++) { + FILE *f = fopen("/dev/null", "rb"); + ASSERT_TRUE(f != nullptr); + dummyFilePointers.push_back(f); + } + for (int i = 0; i < 100; i++) { + PJ_CONTEXT *ctxt = proj_context_create(); + ASSERT_TRUE(ctxt != nullptr); + auto obj = proj_create(ctxt, "EPSG:4326"); + ObjectKeeper keeper(obj); + EXPECT_NE(obj, nullptr); + ctxts.push_back(ctxt); + } + for (PJ_CONTEXT *ctxt : ctxts) { + proj_context_destroy(ctxt); + } + for (FILE *f : dummyFilePointers) { + fclose(f); + } + proj_cleanup(); +} +#endif // !defined(_WIN32) + +// --------------------------------------------------------------------------- + +#ifndef __MINGW32__ +// We need std::thread support + +TEST_F(CApi, concurrent_context) { + // Test that concurrent access to the database is thread safe. + std::vector threads; + for (int i = 0; i < 4; i++) { + threads.emplace_back(std::thread([] { + for (int j = 0; j < 60; j++) { + PJ_CONTEXT *ctxt = proj_context_create(); + { + auto obj = proj_create(ctxt, "EPSG:4326"); + ObjectKeeper keeper(obj); + EXPECT_NE(obj, nullptr); + } + { + auto obj = proj_create( + ctxt, ("EPSG:" + std::to_string(32600 + j)).c_str()); + ObjectKeeper keeper(obj); + EXPECT_NE(obj, nullptr); + } + proj_context_destroy(ctxt); + } + })); + } + for (auto &t : threads) { + t.join(); + } + proj_cleanup(); +} + +#endif // __MINGW32__ + } // namespace -- cgit v1.2.3