Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GDAL Core 4 : * Purpose: Test OSRSetPROJSearchPaths() 5 : * Author: Even Rouault, <even dot rouault at spatialys dot com> 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2019, Even Rouault <even dot rouault at spatialys dot com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #include <stdlib.h> 14 : 15 : #include "cpl_error.h" 16 : #include "cpl_string.h" 17 : #include "ogr_srs_api.h" 18 : #include "cpl_multiproc.h" 19 : 20 : #include "test_data.h" 21 : #include "gtest_include.h" 22 : 23 : namespace 24 : { 25 : 26 : // --------------------------------------------------------------------------- 27 : 28 2 : static void func1(void *) 29 : { 30 2 : OGRSpatialReferenceH hSRS = OSRNewSpatialReference(nullptr); 31 2 : CPLPushErrorHandler(CPLQuietErrorHandler); 32 2 : auto ret = OSRImportFromEPSG(hSRS, 32631); 33 2 : CPLPopErrorHandler(); 34 2 : EXPECT_NE(ret, OGRERR_NONE); 35 2 : OSRDestroySpatialReference(hSRS); 36 2 : } 37 : 38 2 : static void func2(void *) 39 : { 40 2 : OGRSpatialReferenceH hSRS = OSRNewSpatialReference(nullptr); 41 2 : EXPECT_EQ(OSRImportFromEPSG(hSRS, 32631), OGRERR_NONE); 42 2 : OSRDestroySpatialReference(hSRS); 43 2 : } 44 : 45 4 : TEST(test_osr_set_proj_search_paths, test) 46 : { 47 1 : auto tokens = OSRGetPROJSearchPaths(); 48 : 49 : // Overriding PROJ_LIB and PROJ_DATA 50 : static char szPROJ_LIB[] = "PROJ_LIB=/i_do/not_exist"; 51 1 : putenv(szPROJ_LIB); 52 : static char szPROJ_DATA[] = "PROJ_DATA=/i_do/not_exist"; 53 1 : putenv(szPROJ_DATA); 54 : 55 : // Test we can no longer find the database 56 1 : func1(nullptr); 57 : 58 : // In a thread as well 59 1 : auto t1 = CPLCreateJoinableThread(func1, nullptr); 60 1 : CPLJoinThread(t1); 61 : 62 : { 63 1 : const char *const apszDummyPaths[] = {"/i/am/dummy", nullptr}; 64 1 : OSRSetPROJSearchPaths(apszDummyPaths); 65 1 : auto tokens2 = OSRGetPROJSearchPaths(); 66 1 : EXPECT_STREQ(tokens2[0], "/i/am/dummy"); 67 1 : CSLDestroy(tokens2); 68 : } 69 : 70 : // Use OSRSetPROJSearchPaths to restore search paths 71 1 : OSRSetPROJSearchPaths(tokens); 72 : 73 : // This time this should work 74 1 : func2(nullptr); 75 : 76 : // In a thread as well 77 1 : auto t2 = CPLCreateJoinableThread(func2, nullptr); 78 1 : CPLJoinThread(t2); 79 : 80 1 : CSLDestroy(tokens); 81 1 : OSRCleanup(); 82 1 : } 83 : 84 4 : static void osr_cleanup_in_threads_thread_func(void *) 85 : { 86 4 : OGRSpatialReferenceH hSRS = OSRNewSpatialReference(nullptr); 87 4 : EXPECT_EQ(OSRImportFromEPSG(hSRS, 32631), OGRERR_NONE); 88 : 89 : // Test cleanup effect 90 4 : OSRCleanup(); 91 : 92 248 : for (int epsg = 32601; epsg <= 32661; epsg++) 93 : { 94 244 : EXPECT_EQ(OSRImportFromEPSG(hSRS, epsg), OGRERR_NONE); 95 244 : EXPECT_EQ(OSRImportFromEPSG(hSRS, epsg + 100), OGRERR_NONE); 96 : } 97 4 : OSRDestroySpatialReference(hSRS); 98 4 : } 99 : 100 4 : TEST(test_osr_set_proj_search_paths, osr_cleanup_in_threads) 101 : { 102 : // Test fix for #2744 103 : CPLJoinableThread *ahThreads[4]; 104 5 : for (int i = 0; i < 4; i++) 105 : { 106 4 : ahThreads[i] = CPLCreateJoinableThread( 107 : osr_cleanup_in_threads_thread_func, nullptr); 108 : } 109 5 : for (int i = 0; i < 4; i++) 110 : { 111 4 : CPLJoinThread(ahThreads[i]); 112 : } 113 1 : } 114 : 115 4 : TEST(test_osr_set_proj_search_paths, auxiliary_db) 116 : { 117 : // This test use auxiliary database created with proj 6.3.2 118 : // (tested up to 8.0.0) and can be sensitive to future 119 : // database structure change. 120 : // 121 : // See PR https://github.com/OSGeo/gdal/pull/3590 122 : // 123 : // Starting with sqlite 3.41, and commit 124 : // https://github.com/sqlite/sqlite/commit/ed07d0ea765386c5bdf52891154c70f048046e60 125 : // we must use the same exact table definition in the auxiliary db, otherwise 126 : // SQLite3 is confused regarding column types. Hence this PROJ >= 9 check, 127 : // to use a table structure identical to proj.db of PROJ 9. 128 1 : int nPROJMajor = 0; 129 1 : OSRGetPROJVersion(&nPROJMajor, nullptr, nullptr); 130 1 : const char *apszAux0[] = {nPROJMajor >= 9 131 1 : ? TUT_ROOT_DATA_DIR "/test_aux_proj_9.db" 132 : : TUT_ROOT_DATA_DIR "/test_aux.db", 133 1 : nullptr}; 134 1 : OSRSetPROJAuxDbPaths(apszAux0); 135 : 136 1 : CPLStringList aosAux1(OSRGetPROJAuxDbPaths()); 137 1 : ASSERT_EQ(aosAux1.size(), 1); 138 1 : ASSERT_STREQ(apszAux0[0], aosAux1[0]); 139 1 : OGRSpatialReferenceH hSRS = OSRNewSpatialReference(nullptr); 140 1 : EXPECT_EQ(OSRImportFromEPSG(hSRS, 4326), OGRERR_NONE); 141 1 : EXPECT_EQ(OSRImportFromEPSG(hSRS, 111111), OGRERR_NONE); 142 1 : OSRDestroySpatialReference(hSRS); 143 : } 144 : 145 : } // namespace