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