1 /******************************************************************************
2  *
3  * Project:  GDAL Utilities
4  * Purpose:  Command line utility to torture GDAL API on datasets
5  * Author:   Even Rouault, <even dot rouault at spatialys.com>
6  *
7  ******************************************************************************
8  * Copyright (c) 2008-2011, Even Rouault <even dot rouault at spatialys.com>
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  ****************************************************************************/
28 
29 #include "gdal.h"
30 #include "cpl_string.h"
31 #include "cpl_conv.h"
32 
33 #include <cassert>
34 
35 CPL_CVSID("$Id: gdaltorture.cpp 355b41831cd2685c85d1aabe5b95665a2c6e99b7 2019-06-19 17:07:04 +0200 Even Rouault $")
36 
37 /************************************************************************/
38 /*                               Usage()                                */
39 /************************************************************************/
40 
Usage()41 static void Usage()
42 
43 {
44     printf("Usage: gdaltorture [-r] [-u] [-rw] files*\n");
45     exit(1);
46 }
47 
48 /************************************************************************/
49 /*                              TortureDS()                             */
50 /************************************************************************/
51 
TortureBand(GDALRasterBandH hBand,int,int nRecurse)52 static void TortureBand( GDALRasterBandH hBand, int /* bReadWriteOperations */,
53                          int nRecurse )
54 {
55     if( nRecurse > 5 )
56         return;
57 
58     GDALGetRasterDataType(hBand);
59     int nBlockXSize;
60     int nBlockYSize;
61     GDALGetBlockSize(hBand, &nBlockXSize, &nBlockYSize);
62     // GDALRasterAdviseRead
63     // GDALRasterIO
64     // GDALReadBlock
65     // GDALWriteBlock
66     const int nRasterXSize = GDALGetRasterBandXSize(hBand);
67     assert(nRasterXSize >= 0);
68     const int nRasterYSize = GDALGetRasterBandYSize(hBand);
69     assert(nRasterYSize >= 0);
70     GDALGetRasterAccess(hBand);
71     GDALGetBandNumber(hBand);
72     GDALGetBandDataset(hBand);
73     GDALGetRasterColorInterpretation(hBand);
74     // GDALSetRasterColorInterpretation
75     GDALGetRasterColorTable(hBand);
76     // GDALSetRasterColorTable
77     GDALHasArbitraryOverviews (hBand);
78 
79     const int nOverviewCount = GDALGetOverviewCount(hBand);
80     for(int iOverview=0;iOverview<nOverviewCount;iOverview++)
81     {
82         GDALRasterBandH hOverviewBand = GDALGetOverview(hBand, iOverview);
83         if( hOverviewBand )
84             TortureBand(hOverviewBand, false, nRecurse + 1);
85     }
86 
87     int bHasNoData;
88     GDALGetRasterNoDataValue(hBand, &bHasNoData);
89     // GDALSetRasterNoDataValue
90     GDALGetRasterCategoryNames(hBand);
91     // GDALSetRasterCategoryNames
92     int bSuccess;
93     GDALGetRasterMinimum(hBand, &bSuccess);
94     GDALGetRasterMaximum(hBand, &bSuccess);
95     double dfMin, dfMax, dfMean, dfStdDev;
96     GDALGetRasterStatistics(hBand, TRUE, FALSE, &dfMin, &dfMax,
97                             &dfMean, &dfStdDev);
98     // GDALComputeRasterStatistics
99     // GDALSetRasterStatistics
100     GDALGetRasterUnitType(hBand);
101     GDALGetRasterOffset(hBand, &bSuccess);
102     // GDALSetRasterOffset
103     GDALGetRasterScale(hBand, &bSuccess);
104     // GDALSetRasterScale
105     // double adfMinMax[2];
106     // GDALComputeRasterMinMax(hBand, TRUE, adfMinMax);
107     // GDALFlushRasterCache(hBand)
108     // GDALGetDefaultHistogram(
109     //     GDALRasterBandH hBand, double *pdfMin, double *pdfMax,
110     //     int *pnBuckets, int **ppanHistogram, int bForce,
111     //     GDALProgressFunc pfnProgress, void *pProgressData);
112     // GDALSetDefaultHistogram(
113     //     GDALRasterBandH hBand, double dfMin, double dfMax,
114     //     int nBuckets, int *panHistogram);
115     float afSampleBuf;
116     GDALGetRandomRasterSample(hBand, 1, &afSampleBuf);
117     GDALGetRasterSampleOverview(hBand, 0); // returns a hBand
118     // GDALFillRaster
119     // GDALComputeBandStats
120     // GDALOverviewMagnitudeCorrection
121     GDALGetDefaultRAT(hBand);
122     // GDALSetDefaultRAT
123     // GDALAddDerivedBandPixelFunc
124     GDALRasterBandH hMaskBand = GDALGetMaskBand(hBand);
125     if( hMaskBand != hBand )
126         TortureBand(hMaskBand, false, nRecurse + 1);
127     GDALGetMaskFlags(hBand);
128     // GDALCreateMaskBand
129 }
130 
131 /************************************************************************/
132 /*                              TortureDS()                             */
133 /************************************************************************/
134 
TortureDS(const char * pszTarget,bool bReadWriteOperations)135 static void TortureDS( const char *pszTarget, bool bReadWriteOperations )
136 {
137     // hDS = GDALOpen(pszTarget, GA_Update);
138     // GDALClose(hDS);
139 
140     GDALDatasetH hDS = GDALOpen(pszTarget, GA_ReadOnly);
141     if( hDS == nullptr )
142         return;
143 
144     // GDALGetMetadata(GDALMajorObjectH, const char *);
145     // GDALSetMetadata(GDALMajorObjectH, char **, const char *);
146     // GDALGetMetadataItem(GDALMajorObjectH, const char *, const char *);
147     // GDALSetMetadataItem(GDALMajorObjectH, const char *, const char *,
148     //                     const char *);
149     GDALGetDescription(hDS);
150     //GDALSetDescription
151     GDALGetDatasetDriver(hDS);
152     char **papszFileList = GDALGetFileList(hDS);
153     CSLDestroy(papszFileList);
154     const int nXSize = GDALGetRasterXSize(hDS);
155     assert(nXSize >= 0);
156     const int nYSize = GDALGetRasterYSize(hDS);
157     assert(nYSize >= 0);
158     const int nBands = GDALGetRasterCount(hDS);
159     // GDALAddBand
160     // GDALDatasetRasterIO
161     GDALGetProjectionRef(hDS);
162     // GDALSetProjection
163     double adfGeotransform[6] = {};
164     GDALGetGeoTransform(hDS, adfGeotransform);
165     // GDALSetGeoTransform
166     GDALGetGCPCount(hDS);
167     GDALGetGCPProjection(hDS);
168     GDALGetGCPs(hDS);
169     // GDALSetGCPs
170     // GDALGetInternalHandle
171     GDALReferenceDataset(hDS);
172     GDALDereferenceDataset(hDS);
173     // GDALBuildOverviews
174     GDALGetAccess(hDS);
175     // GDALFlushCache
176     // GDALCreateDatasetMaskBand
177     // GDALDatasetCopyWholeRaster
178 
179     for( int iBand = 0; iBand < nBands; iBand++ )
180     {
181         GDALRasterBandH hBand = GDALGetRasterBand(hDS, iBand + 1);
182         if( hBand == nullptr )
183             continue;
184 
185         TortureBand(hBand, bReadWriteOperations, 0);
186     }
187 
188     GDALClose(hDS);
189 }
190 
191 /************************************************************************/
192 /*                       ProcessTortureTarget()                         */
193 /************************************************************************/
194 
ProcessTortureTarget(const char * pszTarget,char ** papszSiblingList,bool bRecursive,bool bReportFailures,bool bReadWriteOperations)195 static void ProcessTortureTarget( const char *pszTarget,
196                                   char **papszSiblingList,
197                                   bool bRecursive, bool bReportFailures,
198                                   bool bReadWriteOperations )
199 {
200     GDALDriverH hDriver = GDALIdentifyDriver(pszTarget, papszSiblingList);
201 
202     if( hDriver != nullptr )
203     {
204         printf("%s: %s\n", pszTarget, GDALGetDriverShortName(hDriver));
205         TortureDS(pszTarget, bReadWriteOperations);
206     }
207     else if( bReportFailures )
208     {
209         printf("%s: unrecognized\n", pszTarget);
210     }
211 
212     if( !bRecursive || hDriver != nullptr )
213         return;
214 
215     VSIStatBufL sStatBuf;
216     if( VSIStatL(pszTarget, &sStatBuf) != 0 ||
217         !VSI_ISDIR(sStatBuf.st_mode) )
218         return;
219 
220     papszSiblingList = VSIReadDir(pszTarget);
221     for( int i = 0; papszSiblingList && papszSiblingList[i]; i++ )
222     {
223         if( EQUAL(papszSiblingList[i],"..") ||
224             EQUAL(papszSiblingList[i],".") )
225             continue;
226 
227         const CPLString osSubTarget =
228             CPLFormFilename(pszTarget, papszSiblingList[i], nullptr);
229 
230         ProcessTortureTarget(osSubTarget, papszSiblingList,
231                              bRecursive, bReportFailures, bReadWriteOperations);
232     }
233     CSLDestroy(papszSiblingList);
234 }
235 
236 /************************************************************************/
237 /*                                main()                                */
238 /************************************************************************/
239 
main(int argc,char ** argv)240 int main( int argc, char **argv )
241 {
242     GDALAllRegister();
243 
244     argc = GDALGeneralCmdLineProcessor(argc, &argv, 0);
245     if( argc < 1 )
246         exit(-argc);
247 
248     if( argc < 2 )
249         Usage();
250 
251 /* -------------------------------------------------------------------- */
252 /*      Scan for command line switches                                   */
253 /* -------------------------------------------------------------------- */
254     char** papszArgv = argv + 1;
255     argc--;
256 
257     bool bRecursive = false;
258     bool bReportFailures = false;
259     bool bReadWriteOperations = false;
260 
261     while( argc > 0 && papszArgv[0][0] == '-' )
262     {
263         if( EQUAL(papszArgv[0], "-r") )
264             bRecursive = true;
265         else if( EQUAL(papszArgv[0], "-u") )
266             bReportFailures = true;
267         else if( EQUAL(papszArgv[0], "-rw") )
268             bReadWriteOperations = true;
269         else
270             Usage();
271 
272         papszArgv++;
273         argc--;
274     }
275 
276 /* -------------------------------------------------------------------- */
277 /*      Process given files.                                            */
278 /* -------------------------------------------------------------------- */
279     while( argc > 0 )
280     {
281         ProcessTortureTarget(papszArgv[0], nullptr,
282                              bRecursive, bReportFailures, bReadWriteOperations);
283         argc--;
284         papszArgv++;
285     }
286 
287 /* -------------------------------------------------------------------- */
288 /*      Cleanup                                                         */
289 /* -------------------------------------------------------------------- */
290     CSLDestroy(argv);
291     GDALDestroyDriverManager();
292 
293     return 0;
294 }
295