LCOV - code coverage report
Current view: top level - autotest/cpp - test_gdal.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 2000 2030 98.5 %
Date: 2024-05-14 13:00:50 Functions: 262 266 98.5 %

          Line data    Source code
       1             : ///////////////////////////////////////////////////////////////////////////////
       2             : //
       3             : // Project:  C++ Test Suite for GDAL/OGR
       4             : // Purpose:  Test general GDAL features.
       5             : // Author:   Mateusz Loskot <mateusz@loskot.net>
       6             : //
       7             : ///////////////////////////////////////////////////////////////////////////////
       8             : // Copyright (c) 2006, Mateusz Loskot <mateusz@loskot.net>
       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_unit_test.h"
      30             : 
      31             : #include "gdal_alg.h"
      32             : #include "gdal_priv.h"
      33             : #include "gdal_utils.h"
      34             : #include "gdal_priv_templates.hpp"
      35             : #include "gdal.h"
      36             : #include "tilematrixset.hpp"
      37             : #include "gdalcachedpixelaccessor.h"
      38             : 
      39             : #include <limits>
      40             : #include <string>
      41             : 
      42             : #include "test_data.h"
      43             : 
      44             : #include "gtest_include.h"
      45             : 
      46             : namespace
      47             : {
      48             : // Common fixture with test data
      49             : struct test_gdal : public ::testing::Test
      50             : {
      51             : };
      52             : 
      53             : // Test GDAL driver manager access
      54           4 : TEST_F(test_gdal, driver_manager)
      55             : {
      56           1 :     GDALDriverManager *drv_mgr = nullptr;
      57           1 :     drv_mgr = GetGDALDriverManager();
      58           1 :     ASSERT_TRUE(nullptr != drv_mgr);
      59             : }
      60             : 
      61             : // Test that GDALRegisterPlugins can be called
      62           4 : TEST_F(test_gdal, register_plugins)
      63             : {
      64           1 :     GDALRegisterPlugins();
      65           1 : }
      66             : 
      67             : // Test that GDALRegisterPlugin can be called and returns an error for a non
      68             : // existing plugin name
      69           4 : TEST_F(test_gdal, register_plugin)
      70             : {
      71           1 :     ASSERT_EQ(GDALRegisterPlugin("rtbreg_non_existing_plugin"), CE_Failure);
      72             : }
      73             : 
      74             : // Test number of registered GDAL drivers
      75           4 : TEST_F(test_gdal, number_of_registered_drivers)
      76             : {
      77             : #ifdef WIN32CE
      78             :     ASSERT_EQ(GDALGetDriverCount(), drv_count_);
      79             : #endif
      80           1 : }
      81             : 
      82             : // Test if AAIGrid driver is registered
      83           4 : TEST_F(test_gdal, aaigrid_is_registered)
      84             : {
      85           1 :     GDALDriverH drv = GDALGetDriverByName("AAIGrid");
      86             : 
      87             : #ifdef FRMT_aaigrid
      88             :     ASSERT_TRUE(NULL != drv);
      89             : #else
      90             :     (void)drv;
      91             : #endif
      92           1 : }
      93             : 
      94             : // Test if DTED driver is registered
      95           4 : TEST_F(test_gdal, dted_is_registered)
      96             : {
      97           1 :     GDALDriverH drv = GDALGetDriverByName("DTED");
      98             : 
      99             : #ifdef FRMT_dted
     100             :     ASSERT_TRUE(NULL != drv);
     101             : #else
     102             :     (void)drv;
     103             : #endif
     104           1 : }
     105             : 
     106             : // Test if GeoTIFF driver is registered
     107           4 : TEST_F(test_gdal, gtiff_is_registered)
     108             : {
     109           1 :     GDALDriverH drv = GDALGetDriverByName("GTiff");
     110             : 
     111             : #ifdef FRMT_gtiff
     112             :     ASSERT_TRUE(NULL != drv);
     113             : #else
     114             :     (void)drv;
     115             : #endif
     116           1 : }
     117             : 
     118             : class DataTypeTupleFixture : public test_gdal,
     119             :                              public ::testing::WithParamInterface<
     120             :                                  std::tuple<GDALDataType, GDALDataType>>
     121             : {
     122             :   public:
     123           1 :     static std::vector<std::tuple<GDALDataType, GDALDataType>> GetTupleValues()
     124             :     {
     125           1 :         std::vector<std::tuple<GDALDataType, GDALDataType>> ret;
     126          15 :         for (GDALDataType eIn = GDT_Byte; eIn < GDT_TypeCount;
     127          14 :              eIn = static_cast<GDALDataType>(eIn + 1))
     128             :         {
     129         210 :             for (GDALDataType eOut = GDT_Byte; eOut < GDT_TypeCount;
     130         196 :                  eOut = static_cast<GDALDataType>(eOut + 1))
     131             :             {
     132         196 :                 ret.emplace_back(std::make_tuple(eIn, eOut));
     133             :             }
     134             :         }
     135           1 :         return ret;
     136             :     }
     137             : };
     138             : 
     139             : // Test GDALDataTypeUnion() on all (GDALDataType, GDALDataType) combinations
     140         393 : TEST_P(DataTypeTupleFixture, GDALDataTypeUnion_generic)
     141             : {
     142         196 :     GDALDataType eDT1 = std::get<0>(GetParam());
     143         196 :     GDALDataType eDT2 = std::get<1>(GetParam());
     144         196 :     GDALDataType eDT = GDALDataTypeUnion(eDT1, eDT2);
     145         196 :     EXPECT_EQ(eDT, GDALDataTypeUnion(eDT2, eDT1));
     146         196 :     EXPECT_GE(GDALGetDataTypeSize(eDT), GDALGetDataTypeSize(eDT1));
     147         196 :     EXPECT_GE(GDALGetDataTypeSize(eDT), GDALGetDataTypeSize(eDT2));
     148         196 :     EXPECT_TRUE((GDALDataTypeIsComplex(eDT) && (GDALDataTypeIsComplex(eDT1) ||
     149             :                                                 GDALDataTypeIsComplex(eDT2))) ||
     150             :                 (!GDALDataTypeIsComplex(eDT) && !GDALDataTypeIsComplex(eDT1) &&
     151             :                  !GDALDataTypeIsComplex(eDT2)));
     152             : 
     153         196 :     EXPECT_TRUE(
     154             :         !(GDALDataTypeIsFloating(eDT1) || GDALDataTypeIsFloating(eDT2)) ||
     155             :         GDALDataTypeIsFloating(eDT));
     156         196 :     EXPECT_TRUE(!(GDALDataTypeIsSigned(eDT1) || GDALDataTypeIsSigned(eDT2)) ||
     157             :                 GDALDataTypeIsSigned(eDT));
     158         196 : }
     159             : 
     160         590 : INSTANTIATE_TEST_SUITE_P(
     161             :     test_gdal, DataTypeTupleFixture,
     162             :     ::testing::ValuesIn(DataTypeTupleFixture::GetTupleValues()),
     163             :     [](const ::testing::TestParamInfo<DataTypeTupleFixture::ParamType> &l_info)
     164             :     {
     165             :         GDALDataType eDT1 = std::get<0>(l_info.param);
     166             :         GDALDataType eDT2 = std::get<1>(l_info.param);
     167             :         return std::string(GDALGetDataTypeName(eDT1)) + "_" +
     168             :                GDALGetDataTypeName(eDT2);
     169             :     });
     170             : 
     171             : // Test GDALDataTypeUnion()
     172           4 : TEST_F(test_gdal, GDALDataTypeUnion_special_cases)
     173             : {
     174           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_Int16, GDT_UInt16), GDT_Int32);
     175           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_Int16, GDT_UInt32), GDT_Int64);
     176           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_UInt32, GDT_Int16), GDT_Int64);
     177           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_Int64, GDT_UInt64), GDT_Float64);
     178           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_Int64, GDT_Float32), GDT_Float64);
     179           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_Int64, GDT_Float64), GDT_Float64);
     180           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_UInt64, GDT_Float32), GDT_Float64);
     181           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_UInt64, GDT_Float64), GDT_Float64);
     182           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_UInt32, GDT_CInt16), GDT_CFloat64);
     183           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_Float32, GDT_CInt32), GDT_CFloat64);
     184           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CInt16, GDT_UInt32), GDT_CFloat64);
     185           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CInt16, GDT_CFloat32), GDT_CFloat32);
     186           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CInt32, GDT_Byte), GDT_CInt32);
     187           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CInt32, GDT_UInt16), GDT_CInt32);
     188           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CInt32, GDT_Int16), GDT_CInt32);
     189           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CInt32, GDT_UInt32), GDT_CFloat64);
     190           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CInt32, GDT_Int32), GDT_CInt32);
     191           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CInt32, GDT_Float32), GDT_CFloat64);
     192           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CInt32, GDT_CInt16), GDT_CInt32);
     193           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CInt32, GDT_CFloat32), GDT_CFloat64);
     194           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CFloat32, GDT_Byte), GDT_CFloat32);
     195           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CFloat32, GDT_UInt16), GDT_CFloat32);
     196           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CFloat32, GDT_Int16), GDT_CFloat32);
     197           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CFloat32, GDT_UInt32), GDT_CFloat64);
     198           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CFloat32, GDT_Int32), GDT_CFloat64);
     199           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CFloat32, GDT_Float32), GDT_CFloat32);
     200           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CFloat32, GDT_CInt16), GDT_CFloat32);
     201           1 :     EXPECT_EQ(GDALDataTypeUnion(GDT_CFloat32, GDT_CInt32), GDT_CFloat64);
     202             : 
     203           1 :     EXPECT_EQ(GDALFindDataType(0, false /* signed */, false /* floating */,
     204             :                                false /* complex */),
     205             :               GDT_Byte);
     206           1 :     EXPECT_EQ(GDALFindDataType(0, true /* signed */, false /* floating */,
     207             :                                false /* complex */),
     208             :               GDT_Int8);
     209           1 :     EXPECT_EQ(GDALFindDataType(0, false /* signed */, false /* floating */,
     210             :                                true /* complex */),
     211             :               GDT_CInt32);
     212           1 :     EXPECT_EQ(GDALFindDataType(0, true /* signed */, false /* floating */,
     213             :                                true /* complex */),
     214             :               GDT_CInt16);
     215           1 :     EXPECT_EQ(GDALFindDataType(0, false /* signed */, true /* floating */,
     216             :                                false /* complex */),
     217             :               GDT_Float32);
     218           1 :     EXPECT_EQ(GDALFindDataType(0, true /* signed */, true /* floating */,
     219             :                                false /* complex */),
     220             :               GDT_Float32);
     221           1 :     EXPECT_EQ(GDALFindDataType(0, false /* signed */, true /* floating */,
     222             :                                true /* complex */),
     223             :               GDT_CFloat32);
     224           1 :     EXPECT_EQ(GDALFindDataType(0, true /* signed */, true /* floating */,
     225             :                                true /* complex */),
     226             :               GDT_CFloat32);
     227             : 
     228           1 :     EXPECT_EQ(GDALFindDataType(8, false /* signed */, false /* floating */,
     229             :                                false /* complex */),
     230             :               GDT_Byte);
     231           1 :     EXPECT_EQ(GDALFindDataType(8, true /* signed */, false /* floating */,
     232             :                                false /* complex */),
     233             :               GDT_Int8);
     234             : 
     235           1 :     EXPECT_EQ(GDALFindDataType(16, false /* signed */, false /* floating */,
     236             :                                false /* complex */),
     237             :               GDT_UInt16);
     238           1 :     EXPECT_EQ(GDALFindDataType(16, true /* signed */, false /* floating */,
     239             :                                false /* complex */),
     240             :               GDT_Int16);
     241             : 
     242           1 :     EXPECT_EQ(GDALFindDataType(32, false /* signed */, false /* floating */,
     243             :                                false /* complex */),
     244             :               GDT_UInt32);
     245           1 :     EXPECT_EQ(GDALFindDataType(32, true /* signed */, false /* floating */,
     246             :                                false /* complex */),
     247             :               GDT_Int32);
     248             : 
     249           1 :     EXPECT_EQ(GDALFindDataType(64, false /* signed */, true /* floating */,
     250             :                                false /* complex */),
     251             :               GDT_Float64);
     252           1 :     EXPECT_EQ(GDALFindDataType(64, false /* signed */, true /* floating */,
     253             :                                true /* complex */),
     254             :               GDT_CFloat64);
     255             : 
     256           1 :     EXPECT_EQ(GDALFindDataType(64, false /* signed */, false /* floating */,
     257             :                                false /* complex */),
     258             :               GDT_UInt64);
     259           1 :     EXPECT_EQ(GDALFindDataType(64, true /* signed */, false /* floating */,
     260             :                                false /* complex */),
     261             :               GDT_Int64);
     262             : 
     263           1 :     EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Byte, -128, 0), GDT_Int16);
     264           1 :     EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Byte, -32768, 0), GDT_Int16);
     265           1 :     EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Byte, -32769, 0), GDT_Int32);
     266           1 :     EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Float32, -99999, 0), GDT_Float32);
     267           1 :     EXPECT_EQ(GDALDataTypeUnionWithValue(GDT_Float32, -99999.9876, 0),
     268             :               GDT_Float64);
     269           1 : }
     270             : 
     271             : // Test GDALAdjustValueToDataType()
     272           4 : TEST_F(test_gdal, GDALAdjustValueToDataType)
     273             : {
     274             :     int bClamped, bRounded;
     275             : 
     276           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Byte, 255.0, nullptr, nullptr) ==
     277             :                 255.0);
     278           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Byte, 255.0, &bClamped,
     279             :                                           &bRounded) == 255.0 &&
     280             :                 !bClamped && !bRounded);
     281           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Byte, 254.4, &bClamped,
     282             :                                           &bRounded) == 254.0 &&
     283             :                 !bClamped && bRounded);
     284           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Byte, -1, &bClamped, &bRounded) ==
     285             :                     0.0 &&
     286             :                 bClamped && !bRounded);
     287           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Byte, 256.0, &bClamped,
     288             :                                           &bRounded) == 255.0 &&
     289             :                 bClamped && !bRounded);
     290             : 
     291           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Int8, -128.0, &bClamped,
     292             :                                           &bRounded) == -128.0 &&
     293             :                 !bClamped && !bRounded);
     294           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Int8, 127.0, &bClamped,
     295             :                                           &bRounded) == 127.0 &&
     296             :                 !bClamped && !bRounded);
     297           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Int8, -127.4, &bClamped,
     298             :                                           &bRounded) == -127.0 &&
     299             :                 !bClamped && bRounded);
     300           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Int8, 126.4, &bClamped,
     301             :                                           &bRounded) == 126.0 &&
     302             :                 !bClamped && bRounded);
     303           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Int8, -129.0, &bClamped,
     304             :                                           &bRounded) == -128.0 &&
     305             :                 bClamped && !bRounded);
     306           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Int8, 128.0, &bClamped,
     307             :                                           &bRounded) == 127.0 &&
     308             :                 bClamped && !bRounded);
     309             : 
     310           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_UInt16, 65535.0, &bClamped,
     311             :                                           &bRounded) == 65535.0 &&
     312             :                 !bClamped && !bRounded);
     313           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_UInt16, 65534.4, &bClamped,
     314             :                                           &bRounded) == 65534.0 &&
     315             :                 !bClamped && bRounded);
     316           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_UInt16, -1, &bClamped,
     317             :                                           &bRounded) == 0.0 &&
     318             :                 bClamped && !bRounded);
     319           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_UInt16, 65536.0, &bClamped,
     320             :                                           &bRounded) == 65535.0 &&
     321             :                 bClamped && !bRounded);
     322             : 
     323           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Int16, -32768.0, &bClamped,
     324             :                                           &bRounded) == -32768.0 &&
     325             :                 !bClamped && !bRounded);
     326           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Int16, 32767.0, &bClamped,
     327             :                                           &bRounded) == 32767.0 &&
     328             :                 !bClamped && !bRounded);
     329           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Int16, -32767.4, &bClamped,
     330             :                                           &bRounded) == -32767.0 &&
     331             :                 !bClamped && bRounded);
     332           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Int16, 32766.4, &bClamped,
     333             :                                           &bRounded) == 32766.0 &&
     334             :                 !bClamped && bRounded);
     335           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Int16, -32769.0, &bClamped,
     336             :                                           &bRounded) == -32768.0 &&
     337             :                 bClamped && !bRounded);
     338           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Int16, 32768.0, &bClamped,
     339             :                                           &bRounded) == 32767.0 &&
     340             :                 bClamped && !bRounded);
     341             : 
     342           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_UInt32, 10000000.0, &bClamped,
     343             :                                           &bRounded) == 10000000.0 &&
     344             :                 !bClamped && !bRounded);
     345           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_UInt32, 10000000.4, &bClamped,
     346             :                                           &bRounded) == 10000000.0 &&
     347             :                 !bClamped && bRounded);
     348           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_UInt32, -1, &bClamped,
     349             :                                           &bRounded) == 0.0 &&
     350             :                 bClamped && !bRounded);
     351             : 
     352           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Int32, -10000000.0, &bClamped,
     353             :                                           &bRounded) == -10000000.0 &&
     354             :                 !bClamped && !bRounded);
     355           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Int32, 10000000.0, &bClamped,
     356             :                                           &bRounded) == 10000000.0 &&
     357             :                 !bClamped && !bRounded);
     358             : 
     359           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_UInt64, 10000000000.0, &bClamped,
     360             :                                           &bRounded) == 10000000000.0 &&
     361             :                 !bClamped && !bRounded);
     362           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_UInt64, 10000000000.4, &bClamped,
     363             :                                           &bRounded) == 10000000000.0 &&
     364             :                 !bClamped && bRounded);
     365           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_UInt64, -1, &bClamped,
     366             :                                           &bRounded) == 0.0 &&
     367             :                 bClamped && !bRounded);
     368             : 
     369           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Int64, -10000000000.0, &bClamped,
     370             :                                           &bRounded) == -10000000000.0 &&
     371             :                 !bClamped && !bRounded);
     372           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Int64, 10000000000.0, &bClamped,
     373             :                                           &bRounded) == 10000000000.0 &&
     374             :                 !bClamped && !bRounded);
     375             : 
     376           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Float32, 0.0, &bClamped,
     377             :                                           &bRounded) == 0.0 &&
     378             :                 !bClamped && !bRounded);
     379           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Float32, 1e-50, &bClamped,
     380             :                                           &bRounded) == 0.0 &&
     381             :                 !bClamped && !bRounded);
     382           1 :     EXPECT_TRUE(
     383             :         GDALAdjustValueToDataType(GDT_Float32, 1.23, &bClamped, &bRounded) ==
     384             :             static_cast<double>(1.23f) &&
     385             :         !bClamped && !bRounded);
     386           1 :     EXPECT_TRUE(
     387             :         GDALAdjustValueToDataType(GDT_Float32, -1e300, &bClamped, &bRounded) ==
     388             :             -std::numeric_limits<float>::max() &&
     389             :         bClamped && !bRounded);
     390           1 :     EXPECT_TRUE(
     391             :         GDALAdjustValueToDataType(GDT_Float32, 1e300, &bClamped, &bRounded) ==
     392             :             std::numeric_limits<float>::max() &&
     393             :         bClamped && !bRounded);
     394           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(
     395             :                     GDT_Float32, std::numeric_limits<float>::infinity(),
     396             :                     &bClamped,
     397             :                     &bRounded) == std::numeric_limits<float>::infinity() &&
     398             :                 !bClamped && !bRounded);
     399           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(
     400             :                     GDT_Float32, -std::numeric_limits<float>::infinity(),
     401             :                     &bClamped,
     402             :                     &bRounded) == -std::numeric_limits<float>::infinity() &&
     403             :                 !bClamped && !bRounded);
     404             :     {
     405           1 :         double dfNan = std::numeric_limits<double>::quiet_NaN();
     406             :         double dfGot =
     407           1 :             GDALAdjustValueToDataType(GDT_Float32, dfNan, &bClamped, &bRounded);
     408           1 :         EXPECT_TRUE(memcmp(&dfNan, &dfGot, sizeof(double)) == 0 && !bClamped &&
     409             :                     !bRounded);
     410             :     }
     411             : 
     412           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Float64, 0.0, &bClamped,
     413             :                                           &bRounded) == 0.0 &&
     414             :                 !bClamped && !bRounded);
     415           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Float64, 1e-50, &bClamped,
     416             :                                           &bRounded) == 1e-50 &&
     417             :                 !bClamped && !bRounded);
     418           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Float64, -1e40, &bClamped,
     419             :                                           &bRounded) == -1e40 &&
     420             :                 !bClamped && !bRounded);
     421           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(GDT_Float64, 1e40, &bClamped,
     422             :                                           &bRounded) == 1e40 &&
     423             :                 !bClamped && !bRounded);
     424           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(
     425             :                     GDT_Float64, std::numeric_limits<float>::infinity(),
     426             :                     &bClamped,
     427             :                     &bRounded) == std::numeric_limits<float>::infinity() &&
     428             :                 !bClamped && !bRounded);
     429           1 :     EXPECT_TRUE(GDALAdjustValueToDataType(
     430             :                     GDT_Float64, -std::numeric_limits<float>::infinity(),
     431             :                     &bClamped,
     432             :                     &bRounded) == -std::numeric_limits<float>::infinity() &&
     433             :                 !bClamped && !bRounded);
     434             :     {
     435           1 :         double dfNan = std::numeric_limits<double>::quiet_NaN();
     436             :         double dfGot =
     437           1 :             GDALAdjustValueToDataType(GDT_Float64, dfNan, &bClamped, &bRounded);
     438           1 :         EXPECT_TRUE(memcmp(&dfNan, &dfGot, sizeof(double)) == 0 && !bClamped &&
     439             :                     !bRounded);
     440             :     }
     441           1 : }
     442             : 
     443             : class FakeBand : public GDALRasterBand
     444             : {
     445             :   protected:
     446           0 :     virtual CPLErr IReadBlock(int, int, void *) override
     447             :     {
     448           0 :         return CE_None;
     449             :     }
     450             : 
     451           1 :     virtual CPLErr IWriteBlock(int, int, void *) override
     452             :     {
     453           1 :         return CE_None;
     454             :     }
     455             : 
     456             :   public:
     457           1 :     FakeBand(int nXSize, int nYSize)
     458           1 :     {
     459           1 :         nBlockXSize = nXSize;
     460           1 :         nBlockYSize = nYSize;
     461           1 :     }
     462             : };
     463             : 
     464             : class DatasetWithErrorInFlushCache : public GDALDataset
     465             : {
     466             :     bool bHasFlushCache;
     467             : 
     468             :   public:
     469           2 :     DatasetWithErrorInFlushCache() : bHasFlushCache(false)
     470             :     {
     471           2 :     }
     472             : 
     473           4 :     ~DatasetWithErrorInFlushCache()
     474           2 :     {
     475           2 :         FlushCache(true);
     476           4 :     }
     477             : 
     478           4 :     virtual CPLErr FlushCache(bool bAtClosing) override
     479             :     {
     480           4 :         CPLErr eErr = CE_None;
     481           4 :         if (!bHasFlushCache)
     482             :         {
     483           2 :             CPLError(CE_Failure, CPLE_AppDefined, "some error");
     484           2 :             eErr = CE_Failure;
     485             :         }
     486           4 :         if (GDALDataset::FlushCache(bAtClosing) != CE_None)
     487           0 :             eErr = CE_Failure;
     488           4 :         bHasFlushCache = true;
     489           4 :         return eErr;
     490             :     }
     491             : 
     492           1 :     CPLErr SetSpatialRef(const OGRSpatialReference *) override
     493             :     {
     494           1 :         return CE_None;
     495             :     }
     496             : 
     497           1 :     virtual CPLErr SetGeoTransform(double *) override
     498             :     {
     499           1 :         return CE_None;
     500             :     }
     501             : 
     502           1 :     static GDALDataset *CreateCopy(const char *, GDALDataset *, int, char **,
     503             :                                    GDALProgressFunc, void *)
     504             :     {
     505           1 :         return new DatasetWithErrorInFlushCache();
     506             :     }
     507             : 
     508           1 :     static GDALDataset *Create(const char *, int nXSize, int nYSize, int,
     509             :                                GDALDataType, char **)
     510             :     {
     511           1 :         DatasetWithErrorInFlushCache *poDS = new DatasetWithErrorInFlushCache();
     512           1 :         poDS->eAccess = GA_Update;
     513           1 :         poDS->nRasterXSize = nXSize;
     514           1 :         poDS->nRasterYSize = nYSize;
     515           1 :         poDS->SetBand(1, new FakeBand(nXSize, nYSize));
     516           1 :         return poDS;
     517             :     }
     518             : };
     519             : 
     520             : // Test that GDALTranslate() detects error in flush cache
     521           4 : TEST_F(test_gdal, GDALTranslate_error_flush_cache)
     522             : {
     523           1 :     GDALDriver *poDriver = new GDALDriver();
     524           1 :     poDriver->SetDescription("DatasetWithErrorInFlushCache");
     525           1 :     poDriver->pfnCreateCopy = DatasetWithErrorInFlushCache::CreateCopy;
     526           1 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     527           1 :     const char *args[] = {"-of", "DatasetWithErrorInFlushCache", nullptr};
     528             :     GDALTranslateOptions *psOptions =
     529           1 :         GDALTranslateOptionsNew((char **)args, nullptr);
     530           1 :     GDALDatasetH hSrcDS = GDALOpen(GCORE_DATA_DIR "byte.tif", GA_ReadOnly);
     531           1 :     CPLErrorReset();
     532           1 :     CPLPushErrorHandler(CPLQuietErrorHandler);
     533           1 :     GDALDatasetH hOutDS = GDALTranslate("", hSrcDS, psOptions, nullptr);
     534           1 :     CPLPopErrorHandler();
     535           1 :     GDALClose(hSrcDS);
     536           1 :     GDALTranslateOptionsFree(psOptions);
     537           1 :     EXPECT_TRUE(hOutDS == nullptr);
     538           1 :     EXPECT_TRUE(CPLGetLastErrorType() != CE_None);
     539           1 :     GetGDALDriverManager()->DeregisterDriver(poDriver);
     540           1 :     delete poDriver;
     541           1 : }
     542             : 
     543             : // Test that GDALWarp() detects error in flush cache
     544           4 : TEST_F(test_gdal, GDALWarp_error_flush_cache)
     545             : {
     546           1 :     GDALDriver *poDriver = new GDALDriver();
     547           1 :     poDriver->SetDescription("DatasetWithErrorInFlushCache");
     548           1 :     poDriver->pfnCreate = DatasetWithErrorInFlushCache::Create;
     549           1 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     550           1 :     const char *args[] = {"-of", "DatasetWithErrorInFlushCache", nullptr};
     551             :     GDALWarpAppOptions *psOptions =
     552           1 :         GDALWarpAppOptionsNew((char **)args, nullptr);
     553           1 :     GDALDatasetH hSrcDS = GDALOpen(GCORE_DATA_DIR "byte.tif", GA_ReadOnly);
     554           1 :     CPLErrorReset();
     555           1 :     CPLPushErrorHandler(CPLQuietErrorHandler);
     556             :     GDALDatasetH hOutDS =
     557           1 :         GDALWarp("/", nullptr, 1, &hSrcDS, psOptions, nullptr);
     558           1 :     CPLPopErrorHandler();
     559           1 :     GDALClose(hSrcDS);
     560           1 :     GDALWarpAppOptionsFree(psOptions);
     561           1 :     EXPECT_TRUE(hOutDS == nullptr);
     562           1 :     EXPECT_TRUE(CPLGetLastErrorType() != CE_None);
     563           1 :     GetGDALDriverManager()->DeregisterDriver(poDriver);
     564           1 :     delete poDriver;
     565           1 : }
     566             : 
     567             : // Test GDALWarp() to VRT and that we can call GDALReleaseDataset() on the
     568             : // source dataset when we want.
     569           4 : TEST_F(test_gdal, GDALWarp_VRT)
     570             : {
     571           1 :     const char *args[] = {"-of", "VRT", nullptr};
     572             :     GDALWarpAppOptions *psOptions =
     573           1 :         GDALWarpAppOptionsNew((char **)args, nullptr);
     574           1 :     GDALDatasetH hSrcDS = GDALOpen(GCORE_DATA_DIR "byte.tif", GA_ReadOnly);
     575           1 :     GDALDatasetH hOutDS = GDALWarp("", nullptr, 1, &hSrcDS, psOptions, nullptr);
     576           1 :     GDALWarpAppOptionsFree(psOptions);
     577           1 :     GDALReleaseDataset(hSrcDS);
     578           1 :     EXPECT_EQ(GDALChecksumImage(GDALGetRasterBand(hOutDS, 1), 0, 0, 20, 20),
     579             :               4672);
     580           1 :     GDALReleaseDataset(hOutDS);
     581           1 : }
     582             : 
     583             : // Test GDALTranslate() to VRT and that we can call GDALReleaseDataset() on the
     584             : // source dataset when we want.
     585           4 : TEST_F(test_gdal, GDALTranslate_VRT)
     586             : {
     587           1 :     const char *args[] = {"-of", "VRT", nullptr};
     588             :     GDALTranslateOptions *psOptions =
     589           1 :         GDALTranslateOptionsNew((char **)args, nullptr);
     590           1 :     GDALDatasetH hSrcDS = GDALOpen(GCORE_DATA_DIR "byte.tif", GA_ReadOnly);
     591           1 :     GDALDatasetH hOutDS = GDALTranslate("", hSrcDS, psOptions, nullptr);
     592           1 :     GDALTranslateOptionsFree(psOptions);
     593           1 :     GDALReleaseDataset(hSrcDS);
     594           1 :     EXPECT_EQ(GDALChecksumImage(GDALGetRasterBand(hOutDS, 1), 0, 0, 20, 20),
     595             :               4672);
     596           1 :     GDALReleaseDataset(hOutDS);
     597           1 : }
     598             : 
     599             : // Test GDALBuildVRT() and that we can call GDALReleaseDataset() on the
     600             : // source dataset when we want.
     601           4 : TEST_F(test_gdal, GDALBuildVRT)
     602             : {
     603           1 :     GDALDatasetH hSrcDS = GDALOpen(GCORE_DATA_DIR "byte.tif", GA_ReadOnly);
     604             :     GDALDatasetH hOutDS =
     605           1 :         GDALBuildVRT("", 1, &hSrcDS, nullptr, nullptr, nullptr);
     606           1 :     GDALReleaseDataset(hSrcDS);
     607           1 :     EXPECT_EQ(GDALChecksumImage(GDALGetRasterBand(hOutDS, 1), 0, 0, 20, 20),
     608             :               4672);
     609           1 :     GDALReleaseDataset(hOutDS);
     610           1 : }
     611             : 
     612             : // Test that GDALSwapWords() with unaligned buffers
     613           4 : TEST_F(test_gdal, GDALSwapWords_unaligned_buffers)
     614             : {
     615           1 :     GByte abyBuffer[8 * 2 + 1] = {0, 1, 2, 3, 4, 5, 6, 7, 255,
     616             :                                   7, 6, 5, 4, 3, 2, 1, 0};
     617           1 :     GDALSwapWords(abyBuffer, 4, 2, 9);
     618           1 :     EXPECT_EQ(abyBuffer[0], 3);
     619           1 :     EXPECT_EQ(abyBuffer[1], 2);
     620           1 :     EXPECT_EQ(abyBuffer[2], 1);
     621           1 :     EXPECT_EQ(abyBuffer[3], 0);
     622             : 
     623           1 :     EXPECT_EQ(abyBuffer[9], 4);
     624           1 :     EXPECT_EQ(abyBuffer[10], 5);
     625           1 :     EXPECT_EQ(abyBuffer[11], 6);
     626           1 :     EXPECT_EQ(abyBuffer[12], 7);
     627           1 :     GDALSwapWords(abyBuffer, 4, 2, 9);
     628             : 
     629           1 :     GDALSwapWords(abyBuffer, 8, 2, 9);
     630           1 :     EXPECT_EQ(abyBuffer[0], 7);
     631           1 :     EXPECT_EQ(abyBuffer[1], 6);
     632           1 :     EXPECT_EQ(abyBuffer[2], 5);
     633           1 :     EXPECT_EQ(abyBuffer[3], 4);
     634           1 :     EXPECT_EQ(abyBuffer[4], 3);
     635           1 :     EXPECT_EQ(abyBuffer[5], 2);
     636           1 :     EXPECT_EQ(abyBuffer[6], 1);
     637           1 :     EXPECT_EQ(abyBuffer[7], 0);
     638             : 
     639           1 :     EXPECT_EQ(abyBuffer[9], 0);
     640           1 :     EXPECT_EQ(abyBuffer[10], 1);
     641           1 :     EXPECT_EQ(abyBuffer[11], 2);
     642           1 :     EXPECT_EQ(abyBuffer[12], 3);
     643           1 :     EXPECT_EQ(abyBuffer[13], 4);
     644           1 :     EXPECT_EQ(abyBuffer[14], 5);
     645           1 :     EXPECT_EQ(abyBuffer[15], 6);
     646           1 :     EXPECT_EQ(abyBuffer[16], 7);
     647           1 :     GDALSwapWords(abyBuffer, 4, 2, 9);
     648           1 : }
     649             : 
     650             : // Test ARE_REAL_EQUAL()
     651           4 : TEST_F(test_gdal, ARE_REAL_EQUAL)
     652             : {
     653           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(0.0, 0.0));
     654           1 :     EXPECT_TRUE(!ARE_REAL_EQUAL(0.0, 0.1));
     655           1 :     EXPECT_TRUE(!ARE_REAL_EQUAL(0.1, 0.0));
     656           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(1.0, 1.0));
     657           1 :     EXPECT_TRUE(!ARE_REAL_EQUAL(1.0, 0.99));
     658           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(-std::numeric_limits<double>::min(),
     659             :                                -std::numeric_limits<double>::min()));
     660           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(std::numeric_limits<double>::min(),
     661             :                                std::numeric_limits<double>::min()));
     662           1 :     EXPECT_TRUE(!ARE_REAL_EQUAL(std::numeric_limits<double>::min(), 0.0));
     663           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(-std::numeric_limits<double>::max(),
     664             :                                -std::numeric_limits<double>::max()));
     665           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(std::numeric_limits<double>::max(),
     666             :                                std::numeric_limits<double>::max()));
     667           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(-std::numeric_limits<double>::infinity(),
     668             :                                -std::numeric_limits<double>::infinity()));
     669           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(std::numeric_limits<double>::infinity(),
     670             :                                std::numeric_limits<double>::infinity()));
     671           1 :     EXPECT_TRUE(!ARE_REAL_EQUAL(std::numeric_limits<double>::infinity(),
     672             :                                 std::numeric_limits<double>::max()));
     673           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(-std::numeric_limits<double>::min(),
     674             :                                -std::numeric_limits<double>::min()));
     675             : 
     676           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(0.0f, 0.0f));
     677           1 :     EXPECT_TRUE(!ARE_REAL_EQUAL(0.0f, 0.1f));
     678           1 :     EXPECT_TRUE(!ARE_REAL_EQUAL(0.1f, 0.0f));
     679           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(1.0f, 1.0f));
     680           1 :     EXPECT_TRUE(!ARE_REAL_EQUAL(1.0f, 0.99f));
     681           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(-std::numeric_limits<float>::min(),
     682             :                                -std::numeric_limits<float>::min()));
     683           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(std::numeric_limits<float>::min(),
     684             :                                std::numeric_limits<float>::min()));
     685           1 :     EXPECT_TRUE(!ARE_REAL_EQUAL(std::numeric_limits<float>::min(), 0.0f));
     686           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(-std::numeric_limits<float>::max(),
     687             :                                -std::numeric_limits<float>::max()));
     688           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(std::numeric_limits<float>::max(),
     689             :                                std::numeric_limits<float>::max()));
     690           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(-std::numeric_limits<float>::infinity(),
     691             :                                -std::numeric_limits<float>::infinity()));
     692           1 :     EXPECT_TRUE(ARE_REAL_EQUAL(std::numeric_limits<float>::infinity(),
     693             :                                std::numeric_limits<float>::infinity()));
     694           1 :     EXPECT_TRUE(!ARE_REAL_EQUAL(std::numeric_limits<float>::infinity(),
     695             :                                 std::numeric_limits<float>::max()));
     696           1 : }
     697             : 
     698             : // Test GDALIsValueInRange()
     699           4 : TEST_F(test_gdal, GDALIsValueInRange)
     700             : {
     701           1 :     EXPECT_TRUE(GDALIsValueInRange<GByte>(0));
     702           1 :     EXPECT_TRUE(GDALIsValueInRange<GByte>(255));
     703           1 :     EXPECT_TRUE(!GDALIsValueInRange<GByte>(-1));
     704           1 :     EXPECT_TRUE(!GDALIsValueInRange<GByte>(256));
     705           1 :     EXPECT_TRUE(GDALIsValueInRange<GInt8>(-128));
     706           1 :     EXPECT_TRUE(GDALIsValueInRange<GInt8>(127));
     707           1 :     EXPECT_TRUE(!GDALIsValueInRange<GInt8>(-129));
     708           1 :     EXPECT_TRUE(!GDALIsValueInRange<GInt8>(128));
     709           1 :     EXPECT_TRUE(GDALIsValueInRange<float>(std::numeric_limits<float>::max()));
     710           1 :     EXPECT_TRUE(
     711             :         GDALIsValueInRange<float>(std::numeric_limits<float>::infinity()));
     712           1 :     EXPECT_TRUE(!GDALIsValueInRange<float>(std::numeric_limits<double>::max()));
     713           1 :     EXPECT_TRUE(
     714             :         GDALIsValueInRange<double>(std::numeric_limits<double>::infinity()));
     715           1 :     EXPECT_TRUE(!GDALIsValueInRange<double>(CPLAtof("nan")));
     716           1 :     EXPECT_TRUE(!GDALIsValueInRange<float>(CPLAtof("nan")));
     717           1 :     EXPECT_TRUE(!GDALIsValueInRange<GByte>(CPLAtof("nan")));
     718           1 : }
     719             : 
     720             : // Test GDALDataTypeIsInteger()
     721           4 : TEST_F(test_gdal, GDALDataTypeIsInteger)
     722             : {
     723           1 :     EXPECT_TRUE(!GDALDataTypeIsInteger(GDT_Unknown));
     724           1 :     EXPECT_EQ(GDALDataTypeIsInteger(GDT_Byte), TRUE);
     725           1 :     EXPECT_EQ(GDALDataTypeIsInteger(GDT_Int8), TRUE);
     726           1 :     EXPECT_EQ(GDALDataTypeIsInteger(GDT_UInt16), TRUE);
     727           1 :     EXPECT_EQ(GDALDataTypeIsInteger(GDT_Int16), TRUE);
     728           1 :     EXPECT_EQ(GDALDataTypeIsInteger(GDT_UInt32), TRUE);
     729           1 :     EXPECT_EQ(GDALDataTypeIsInteger(GDT_Int32), TRUE);
     730           1 :     EXPECT_EQ(GDALDataTypeIsInteger(GDT_UInt64), TRUE);
     731           1 :     EXPECT_EQ(GDALDataTypeIsInteger(GDT_Int64), TRUE);
     732           1 :     EXPECT_TRUE(!GDALDataTypeIsInteger(GDT_Float32));
     733           1 :     EXPECT_TRUE(!GDALDataTypeIsInteger(GDT_Float64));
     734           1 :     EXPECT_EQ(GDALDataTypeIsInteger(GDT_CInt16), TRUE);
     735           1 :     EXPECT_EQ(GDALDataTypeIsInteger(GDT_CInt32), TRUE);
     736           1 :     EXPECT_TRUE(!GDALDataTypeIsInteger(GDT_CFloat32));
     737           1 :     EXPECT_TRUE(!GDALDataTypeIsInteger(GDT_CFloat64));
     738           1 : }
     739             : 
     740             : // Test GDALDataTypeIsFloating()
     741           4 : TEST_F(test_gdal, GDALDataTypeIsFloating)
     742             : {
     743           1 :     EXPECT_TRUE(!GDALDataTypeIsFloating(GDT_Unknown));
     744           1 :     EXPECT_TRUE(!GDALDataTypeIsFloating(GDT_Byte));
     745           1 :     EXPECT_TRUE(!GDALDataTypeIsFloating(GDT_Int8));
     746           1 :     EXPECT_TRUE(!GDALDataTypeIsFloating(GDT_UInt16));
     747           1 :     EXPECT_TRUE(!GDALDataTypeIsFloating(GDT_Int16));
     748           1 :     EXPECT_TRUE(!GDALDataTypeIsFloating(GDT_UInt32));
     749           1 :     EXPECT_TRUE(!GDALDataTypeIsFloating(GDT_Int32));
     750           1 :     EXPECT_TRUE(!GDALDataTypeIsFloating(GDT_UInt64));
     751           1 :     EXPECT_TRUE(!GDALDataTypeIsFloating(GDT_Int64));
     752           1 :     EXPECT_EQ(GDALDataTypeIsFloating(GDT_Float32), TRUE);
     753           1 :     EXPECT_EQ(GDALDataTypeIsFloating(GDT_Float64), TRUE);
     754           1 :     EXPECT_TRUE(!GDALDataTypeIsFloating(GDT_CInt16));
     755           1 :     EXPECT_TRUE(!GDALDataTypeIsFloating(GDT_CInt32));
     756           1 :     EXPECT_EQ(GDALDataTypeIsFloating(GDT_CFloat32), TRUE);
     757           1 :     EXPECT_EQ(GDALDataTypeIsFloating(GDT_CFloat64), TRUE);
     758           1 : }
     759             : 
     760             : // Test GDALDataTypeIsComplex()
     761           4 : TEST_F(test_gdal, GDALDataTypeIsComplex)
     762             : {
     763           1 :     EXPECT_TRUE(!GDALDataTypeIsComplex(GDT_Unknown));
     764           1 :     EXPECT_TRUE(!GDALDataTypeIsComplex(GDT_Byte));
     765           1 :     EXPECT_TRUE(!GDALDataTypeIsComplex(GDT_Int8));
     766           1 :     EXPECT_TRUE(!GDALDataTypeIsComplex(GDT_UInt16));
     767           1 :     EXPECT_TRUE(!GDALDataTypeIsComplex(GDT_Int16));
     768           1 :     EXPECT_TRUE(!GDALDataTypeIsComplex(GDT_UInt32));
     769           1 :     EXPECT_TRUE(!GDALDataTypeIsComplex(GDT_Int32));
     770           1 :     EXPECT_TRUE(!GDALDataTypeIsComplex(GDT_UInt64));
     771           1 :     EXPECT_TRUE(!GDALDataTypeIsComplex(GDT_Int64));
     772           1 :     EXPECT_TRUE(!GDALDataTypeIsComplex(GDT_Float32));
     773           1 :     EXPECT_TRUE(!GDALDataTypeIsComplex(GDT_Float64));
     774           1 :     EXPECT_EQ(GDALDataTypeIsComplex(GDT_CInt16), TRUE);
     775           1 :     EXPECT_EQ(GDALDataTypeIsComplex(GDT_CInt32), TRUE);
     776           1 :     EXPECT_EQ(GDALDataTypeIsComplex(GDT_CFloat32), TRUE);
     777           1 :     EXPECT_EQ(GDALDataTypeIsComplex(GDT_CFloat64), TRUE);
     778           1 : }
     779             : 
     780             : // Test GDALDataTypeIsConversionLossy()
     781           4 : TEST_F(test_gdal, GDALDataTypeIsConversionLossy)
     782             : {
     783           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Byte, GDT_Byte));
     784           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Byte, GDT_Int8));
     785           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Byte, GDT_UInt16));
     786           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Byte, GDT_Int16));
     787           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Byte, GDT_UInt32));
     788           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Byte, GDT_Int32));
     789           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Byte, GDT_UInt64));
     790           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Byte, GDT_Int64));
     791           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Byte, GDT_Float32));
     792           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Byte, GDT_Float64));
     793           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Byte, GDT_CInt16));
     794           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Byte, GDT_CInt32));
     795           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Byte, GDT_CFloat32));
     796           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Byte, GDT_CFloat64));
     797             : 
     798           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int8, GDT_Byte));
     799           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int8, GDT_Int8));
     800           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int8, GDT_UInt16));
     801           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int8, GDT_Int16));
     802           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int8, GDT_UInt32));
     803           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int8, GDT_Int32));
     804           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int8, GDT_UInt64));
     805           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int8, GDT_Int64));
     806           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int8, GDT_Float32));
     807           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int8, GDT_Float64));
     808           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int8, GDT_CInt16));
     809           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int8, GDT_CInt32));
     810           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int8, GDT_CFloat32));
     811           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int8, GDT_CFloat64));
     812             : 
     813           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_Byte));
     814           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_Int8));
     815           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_UInt16));
     816           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_Int16));
     817           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_UInt32));
     818           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_Int32));
     819           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_UInt64));
     820           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_Int64));
     821           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_Float32));
     822           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_Float64));
     823           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_CInt16));
     824           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_CInt32));
     825           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_CFloat32));
     826           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_CFloat64));
     827             : 
     828           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int16, GDT_Byte));
     829           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int16, GDT_Int8));
     830           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int16, GDT_UInt16));
     831           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int16, GDT_Int16));
     832           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int16, GDT_UInt32));
     833           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int16, GDT_Int32));
     834           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int16, GDT_UInt64));
     835           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int16, GDT_Int64));
     836           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int16, GDT_Float32));
     837           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int16, GDT_Float64));
     838           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int16, GDT_CInt16));
     839           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int16, GDT_CInt32));
     840           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int16, GDT_CFloat32));
     841           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int16, GDT_CFloat64));
     842             : 
     843           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_Byte));
     844           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_UInt16));
     845           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_Int16));
     846           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_UInt32));
     847           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_Int32));
     848           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_UInt64));
     849           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_Int64));
     850           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_Float32));
     851           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_Float64));
     852           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_CInt16));
     853           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_CInt32));
     854           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_CFloat32));
     855           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_CFloat64));
     856             : 
     857           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int32, GDT_Byte));
     858           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int32, GDT_UInt16));
     859           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int32, GDT_Int16));
     860           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int32, GDT_UInt32));
     861           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int32, GDT_Int32));
     862           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int32, GDT_UInt64));
     863           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int32, GDT_Int64));
     864           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int32, GDT_Float32));
     865           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int32, GDT_Float64));
     866           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int32, GDT_CInt16));
     867           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int32, GDT_CInt32));
     868           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int32, GDT_CFloat32));
     869           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int32, GDT_CFloat64));
     870             : 
     871           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_Byte));
     872           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_UInt16));
     873           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_Int16));
     874           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_UInt32));
     875           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_Int32));
     876           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_UInt64));
     877           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_Int64));
     878           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_Float32));
     879           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_Float64));
     880           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_CInt16));
     881           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_CInt32));
     882           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_CFloat32));
     883           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_CFloat64));
     884             : 
     885           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int64, GDT_Byte));
     886           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int64, GDT_UInt16));
     887           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int64, GDT_Int16));
     888           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int64, GDT_UInt32));
     889           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int64, GDT_Int32));
     890           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int64, GDT_UInt64));
     891           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Int64, GDT_Int64));
     892           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int64, GDT_Float32));
     893           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int64, GDT_Float64));
     894           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int64, GDT_CInt16));
     895           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int64, GDT_CInt32));
     896           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int64, GDT_CFloat32));
     897           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Int64, GDT_CFloat64));
     898             : 
     899           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float32, GDT_Byte));
     900           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float32, GDT_UInt16));
     901           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float32, GDT_Int16));
     902           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float32, GDT_UInt32));
     903           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float32, GDT_Int32));
     904           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float32, GDT_UInt64));
     905           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float32, GDT_Int64));
     906           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Float32, GDT_Float32));
     907           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Float32, GDT_Float64));
     908           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float32, GDT_CInt16));
     909           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float32, GDT_CInt32));
     910           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Float32, GDT_CFloat32));
     911           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Float32, GDT_CFloat64));
     912             : 
     913           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float64, GDT_Byte));
     914           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float64, GDT_UInt16));
     915           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float64, GDT_Int16));
     916           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float64, GDT_UInt32));
     917           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float64, GDT_Int32));
     918           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float64, GDT_UInt64));
     919           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float64, GDT_Int64));
     920           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float64, GDT_Float32));
     921           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Float64, GDT_Float64));
     922           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float64, GDT_CInt16));
     923           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float64, GDT_CInt32));
     924           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_Float64, GDT_CFloat32));
     925           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_Float64, GDT_CFloat64));
     926             : 
     927           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_Byte));
     928           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_UInt16));
     929           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_Int16));
     930           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_UInt32));
     931           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_Int32));
     932           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_UInt64));
     933           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_Int64));
     934           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_Float32));
     935           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_Float64));
     936           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_CInt16));
     937           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_CInt32));
     938           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_CFloat32));
     939           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_CFloat64));
     940             : 
     941           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_Byte));
     942           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_UInt16));
     943           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_Int16));
     944           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_UInt32));
     945           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_Int32));
     946           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_UInt64));
     947           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_Int64));
     948           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_Float32));
     949           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_Float64));
     950           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_CInt16));
     951           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_CInt32));
     952           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_CFloat32));
     953           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_CFloat64));
     954             : 
     955           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_Byte));
     956           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_UInt16));
     957           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_Int16));
     958           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_UInt32));
     959           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_Int32));
     960           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_UInt64));
     961           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_Int64));
     962           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_Float32));
     963           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_Float64));
     964           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_CInt16));
     965           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_CInt32));
     966           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_CFloat32));
     967           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_CFloat64));
     968             : 
     969           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_Byte));
     970           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_UInt16));
     971           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_Int16));
     972           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_UInt32));
     973           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_Int32));
     974           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_UInt64));
     975           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_Int64));
     976           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_Float32));
     977           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_Float64));
     978           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_CInt16));
     979           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_CInt32));
     980           1 :     EXPECT_TRUE(GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_CFloat32));
     981           1 :     EXPECT_TRUE(!GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_CFloat64));
     982           1 : }
     983             : 
     984             : // Test GDALDataset::GetBands()
     985           4 : TEST_F(test_gdal, GDALDataset_GetBands)
     986             : {
     987             :     GDALDatasetUniquePtr poDS(GDALDriver::FromHandle(GDALGetDriverByName("MEM"))
     988           1 :                                   ->Create("", 1, 1, 3, GDT_Byte, nullptr));
     989           1 :     int nExpectedNumber = 1;
     990           4 :     for (auto &&poBand : poDS->GetBands())
     991             :     {
     992           3 :         EXPECT_EQ(poBand->GetBand(), nExpectedNumber);
     993           3 :         nExpectedNumber++;
     994             :     }
     995           1 :     ASSERT_EQ(nExpectedNumber, 3 + 1);
     996             : 
     997           1 :     ASSERT_EQ(poDS->GetBands().size(), 3U);
     998           1 :     EXPECT_EQ(poDS->GetBands()[0], poDS->GetRasterBand(1));
     999           1 :     EXPECT_EQ(poDS->GetBands()[static_cast<size_t>(0)], poDS->GetRasterBand(1));
    1000             : }
    1001             : 
    1002           4 : TEST_F(test_gdal, GDALExtendedDataType)
    1003             : {
    1004             :     // non-null string to string
    1005             :     {
    1006           1 :         const char *srcPtr = "foo";
    1007           1 :         char *dstPtr = nullptr;
    1008           1 :         GDALExtendedDataType::CopyValue(
    1009           2 :             &srcPtr, GDALExtendedDataType::CreateString(), &dstPtr,
    1010           2 :             GDALExtendedDataType::CreateString());
    1011           1 :         EXPECT_TRUE(dstPtr != nullptr);
    1012             :         // Coverity isn't smart enough to figure out that GetClass() of
    1013             :         // CreateString() is GEDTC_STRING and then takes the wrong path
    1014             :         // in CopyValue() and makes wrong assumptions.
    1015             :         // coverity[string_null]
    1016           1 :         EXPECT_STREQ(dstPtr, srcPtr);
    1017             :         // coverity[incorrect_free]
    1018           1 :         CPLFree(dstPtr);
    1019             :     }
    1020             :     // null string to string
    1021             :     {
    1022           1 :         const char *srcPtr = nullptr;
    1023           1 :         char *dstPtr = nullptr;
    1024           1 :         GDALExtendedDataType::CopyValue(
    1025           2 :             &srcPtr, GDALExtendedDataType::CreateString(), &dstPtr,
    1026           2 :             GDALExtendedDataType::CreateString());
    1027           1 :         EXPECT_TRUE(dstPtr == nullptr);
    1028             :     }
    1029             :     // non-null string to Int32
    1030             :     {
    1031           1 :         const char *srcPtr = "2";
    1032           1 :         int32_t nVal = 1;
    1033           1 :         GDALExtendedDataType::CopyValue(
    1034           2 :             &srcPtr, GDALExtendedDataType::CreateString(), &nVal,
    1035           2 :             GDALExtendedDataType::Create(GDT_Int32));
    1036           1 :         EXPECT_EQ(nVal, 2);
    1037             :     }
    1038             :     // null string to Int32
    1039             :     {
    1040           1 :         const char *srcPtr = nullptr;
    1041           1 :         int32_t nVal = 1;
    1042           1 :         GDALExtendedDataType::CopyValue(
    1043           2 :             &srcPtr, GDALExtendedDataType::CreateString(), &nVal,
    1044           2 :             GDALExtendedDataType::Create(GDT_Int32));
    1045           1 :         EXPECT_EQ(nVal, 0);
    1046             :     }
    1047             :     // non-null string to Int64
    1048             :     {
    1049           1 :         const char *srcPtr = "2";
    1050           1 :         int64_t nVal = 1;
    1051           1 :         GDALExtendedDataType::CopyValue(
    1052           2 :             &srcPtr, GDALExtendedDataType::CreateString(), &nVal,
    1053           2 :             GDALExtendedDataType::Create(GDT_Int64));
    1054           1 :         EXPECT_EQ(nVal, 2);
    1055             :     }
    1056             :     // null string to Int64
    1057             :     {
    1058           1 :         const char *srcPtr = nullptr;
    1059           1 :         int64_t nVal = 1;
    1060           1 :         GDALExtendedDataType::CopyValue(
    1061           2 :             &srcPtr, GDALExtendedDataType::CreateString(), &nVal,
    1062           2 :             GDALExtendedDataType::Create(GDT_Int64));
    1063           1 :         EXPECT_EQ(nVal, 0);
    1064             :     }
    1065             :     // non-null string to UInt64
    1066             :     {
    1067           1 :         char *srcPtr = nullptr;
    1068           1 :         uint64_t nVal = 1;
    1069           1 :         GDALExtendedDataType::CopyValue(
    1070           2 :             &srcPtr, GDALExtendedDataType::CreateString(), &nVal,
    1071           2 :             GDALExtendedDataType::Create(GDT_UInt64));
    1072           1 :         EXPECT_EQ(nVal, 0U);
    1073             :     }
    1074             :     // non-null string to Int64
    1075             :     {
    1076           1 :         const char *srcPtr = "2";
    1077           1 :         uint64_t nVal = 1;
    1078           1 :         GDALExtendedDataType::CopyValue(
    1079           2 :             &srcPtr, GDALExtendedDataType::CreateString(), &nVal,
    1080           2 :             GDALExtendedDataType::Create(GDT_UInt64));
    1081           1 :         EXPECT_EQ(nVal, 2U);
    1082             :     }
    1083             : 
    1084             :     class myArray : public GDALMDArray
    1085             :     {
    1086             :         GDALExtendedDataType m_dt;
    1087             :         std::vector<std::shared_ptr<GDALDimension>> m_dims;
    1088             :         std::vector<GUInt64> m_blockSize;
    1089             :         const std::string m_osEmptyFilename{};
    1090             : 
    1091             :         static std::vector<std::shared_ptr<GDALDimension>>
    1092           9 :         BuildDims(const std::vector<GUInt64> &sizes)
    1093             :         {
    1094           9 :             std::vector<std::shared_ptr<GDALDimension>> dims;
    1095          33 :             for (const auto sz : sizes)
    1096             :             {
    1097             :                 dims.emplace_back(
    1098          24 :                     std::make_shared<GDALDimension>("", "", "", "", sz));
    1099             :             }
    1100           9 :             return dims;
    1101             :         }
    1102             : 
    1103             :       protected:
    1104           0 :         bool IRead(const GUInt64 *, const size_t *, const GInt64 *,
    1105             :                    const GPtrDiff_t *, const GDALExtendedDataType &,
    1106             :                    void *) const override
    1107             :         {
    1108           0 :             return false;
    1109             :         }
    1110             : 
    1111             :       public:
    1112           8 :         myArray(GDALDataType eDT, const std::vector<GUInt64> &sizes,
    1113             :                 const std::vector<GUInt64> &blocksizes)
    1114           8 :             : GDALAbstractMDArray("", "array"), GDALMDArray("", "array"),
    1115             :               m_dt(GDALExtendedDataType::Create(eDT)), m_dims(BuildDims(sizes)),
    1116           8 :               m_blockSize(blocksizes)
    1117             :         {
    1118           8 :         }
    1119             : 
    1120           1 :         myArray(const GDALExtendedDataType &dt,
    1121             :                 const std::vector<GUInt64> &sizes,
    1122             :                 const std::vector<GUInt64> &blocksizes)
    1123           1 :             : GDALAbstractMDArray("", "array"), GDALMDArray("", "array"),
    1124           1 :               m_dt(dt), m_dims(BuildDims(sizes)), m_blockSize(blocksizes)
    1125             :         {
    1126           1 :         }
    1127             : 
    1128           0 :         bool IsWritable() const override
    1129             :         {
    1130           0 :             return true;
    1131             :         }
    1132             : 
    1133           0 :         const std::string &GetFilename() const override
    1134             :         {
    1135           0 :             return m_osEmptyFilename;
    1136             :         }
    1137             : 
    1138             :         static std::shared_ptr<myArray>
    1139           1 :         Create(GDALDataType eDT, const std::vector<GUInt64> &sizes,
    1140             :                const std::vector<GUInt64> &blocksizes)
    1141             :         {
    1142             :             auto ar(
    1143           1 :                 std::shared_ptr<myArray>(new myArray(eDT, sizes, blocksizes)));
    1144           1 :             ar->SetSelf(ar);
    1145           1 :             return ar;
    1146             :         }
    1147             : 
    1148             :         static std::shared_ptr<myArray>
    1149           1 :         Create(const GDALExtendedDataType &dt,
    1150             :                const std::vector<GUInt64> &sizes,
    1151             :                const std::vector<GUInt64> &blocksizes)
    1152             :         {
    1153             :             auto ar(
    1154           1 :                 std::shared_ptr<myArray>(new myArray(dt, sizes, blocksizes)));
    1155           1 :             ar->SetSelf(ar);
    1156           1 :             return ar;
    1157             :         }
    1158             : 
    1159             :         const std::vector<std::shared_ptr<GDALDimension>> &
    1160          74 :         GetDimensions() const override
    1161             :         {
    1162          74 :             return m_dims;
    1163             :         }
    1164             : 
    1165          14 :         const GDALExtendedDataType &GetDataType() const override
    1166             :         {
    1167          14 :             return m_dt;
    1168             :         }
    1169             : 
    1170          10 :         std::vector<GUInt64> GetBlockSize() const override
    1171             :         {
    1172          10 :             return m_blockSize;
    1173             :         }
    1174             :     };
    1175             : 
    1176             :     {
    1177           3 :         auto ar(myArray::Create(GDT_UInt16, {3000, 1000, 2000}, {32, 64, 128}));
    1178           1 :         EXPECT_EQ(ar->at(0)->GetDimensionCount(), 2U);
    1179           1 :         EXPECT_EQ(ar->at(2999, 999, 1999)->GetDimensionCount(), 0U);
    1180           1 :         CPLPushErrorHandler(CPLQuietErrorHandler);
    1181           1 :         EXPECT_TRUE(ar->at(3000, 0, 0) == nullptr);
    1182           1 :         EXPECT_TRUE(ar->at(0, 0, 0, 0) == nullptr);
    1183           1 :         EXPECT_TRUE((*ar)["foo"] == nullptr);
    1184           1 :         CPLPopErrorHandler();
    1185             :     }
    1186             : 
    1187             :     {
    1188           2 :         std::vector<std::unique_ptr<GDALEDTComponent>> comps;
    1189             :         comps.emplace_back(
    1190           4 :             std::unique_ptr<GDALEDTComponent>(new GDALEDTComponent(
    1191           3 :                 "f\\o\"o", 0, GDALExtendedDataType::Create(GDT_Int32))));
    1192           3 :         auto dt(GDALExtendedDataType::Create("", 4, std::move(comps)));
    1193           3 :         auto ar(myArray::Create(dt, {3000, 1000, 2000}, {32, 64, 128}));
    1194           1 :         EXPECT_TRUE((*ar)["f\\o\"o"] != nullptr);
    1195             :     }
    1196             : 
    1197             :     {
    1198           3 :         myArray ar(GDT_UInt16, {}, {});
    1199             : 
    1200           1 :         CPLPushErrorHandler(CPLQuietErrorHandler);
    1201           1 :         EXPECT_TRUE(ar.GetView("[...]") == nullptr);
    1202           1 :         CPLPopErrorHandler();
    1203             : 
    1204           2 :         auto cs = ar.GetProcessingChunkSize(0);
    1205           1 :         EXPECT_EQ(cs.size(), 0U);
    1206             : 
    1207             :         struct TmpStructNoDim
    1208             :         {
    1209           1 :             static bool func(GDALAbstractMDArray *p_ar,
    1210             :                              const GUInt64 *chunk_array_start_idx,
    1211             :                              const size_t *chunk_count, GUInt64 iCurChunk,
    1212             :                              GUInt64 nChunkCount, void *user_data)
    1213             :             {
    1214           1 :                 EXPECT_TRUE(p_ar->GetName() == "array");
    1215           1 :                 EXPECT_TRUE(chunk_array_start_idx == nullptr);
    1216           1 :                 EXPECT_TRUE(chunk_count == nullptr);
    1217           1 :                 EXPECT_EQ(iCurChunk, 1U);
    1218           1 :                 EXPECT_EQ(nChunkCount, 1U);
    1219           1 :                 *static_cast<bool *>(user_data) = true;
    1220           1 :                 return true;
    1221             :             }
    1222             :         };
    1223             : 
    1224           1 :         bool b = false;
    1225           1 :         ar.ProcessPerChunk(nullptr, nullptr, nullptr, TmpStructNoDim::func, &b);
    1226           1 :         EXPECT_TRUE(b);
    1227             :     }
    1228             : 
    1229             :     struct ChunkDef
    1230             :     {
    1231             :         std::vector<GUInt64> array_start_idx;
    1232             :         std::vector<GUInt64> count;
    1233             :     };
    1234             : 
    1235             :     struct TmpStruct
    1236             :     {
    1237          16 :         static bool func(GDALAbstractMDArray *p_ar,
    1238             :                          const GUInt64 *chunk_array_start_idx,
    1239             :                          const size_t *chunk_count, GUInt64 iCurChunk,
    1240             :                          GUInt64 nChunkCount, void *user_data)
    1241             :         {
    1242          16 :             EXPECT_EQ(p_ar->GetName(), "array");
    1243          16 :             std::vector<ChunkDef> *p_chunkDefs =
    1244             :                 static_cast<std::vector<ChunkDef> *>(user_data);
    1245          32 :             std::vector<GUInt64> v_chunk_array_start_idx;
    1246             :             v_chunk_array_start_idx.insert(
    1247           0 :                 v_chunk_array_start_idx.end(), chunk_array_start_idx,
    1248          16 :                 chunk_array_start_idx + p_ar->GetDimensionCount());
    1249          32 :             std::vector<GUInt64> v_chunk_count;
    1250           0 :             v_chunk_count.insert(v_chunk_count.end(), chunk_count,
    1251          16 :                                  chunk_count + p_ar->GetDimensionCount());
    1252          16 :             ChunkDef chunkDef;
    1253          16 :             chunkDef.array_start_idx = std::move(v_chunk_array_start_idx);
    1254          16 :             chunkDef.count = std::move(v_chunk_count);
    1255          16 :             p_chunkDefs->emplace_back(std::move(chunkDef));
    1256          16 :             EXPECT_EQ(p_chunkDefs->size(), iCurChunk);
    1257          16 :             EXPECT_TRUE(iCurChunk > 0);
    1258          16 :             EXPECT_TRUE(iCurChunk <= nChunkCount);
    1259          32 :             return true;
    1260             :         }
    1261             :     };
    1262             : 
    1263             :     {
    1264           3 :         myArray ar(GDT_UInt16, {3000, 1000, 2000}, {32, 64, 128});
    1265             :         {
    1266           2 :             auto cs = ar.GetProcessingChunkSize(0);
    1267           1 :             EXPECT_EQ(cs.size(), 3U);
    1268           1 :             EXPECT_EQ(cs[0], 32U);
    1269           1 :             EXPECT_EQ(cs[1], 64U);
    1270           1 :             EXPECT_EQ(cs[2], 128U);
    1271             :         }
    1272             :         {
    1273           2 :             auto cs = ar.GetProcessingChunkSize(40 * 1000 * 1000);
    1274           1 :             EXPECT_EQ(cs.size(), 3U);
    1275           1 :             EXPECT_EQ(cs[0], 32U);
    1276           1 :             EXPECT_EQ(cs[1], 256U);
    1277           1 :             EXPECT_EQ(cs[2], 2000U);
    1278             : 
    1279           2 :             std::vector<ChunkDef> chunkDefs;
    1280             : 
    1281             :             // Error cases of input parameters of ProcessPerChunk()
    1282             :             {
    1283             :                 // array_start_idx[0] + count[0] > 3000
    1284           2 :                 std::vector<GUInt64> array_start_idx{1, 0, 0};
    1285           2 :                 std::vector<GUInt64> count{3000, 1000, 2000};
    1286           1 :                 CPLPushErrorHandler(CPLQuietErrorHandler);
    1287           1 :                 EXPECT_TRUE(!ar.ProcessPerChunk(array_start_idx.data(),
    1288             :                                                 count.data(), cs.data(),
    1289             :                                                 TmpStruct::func, &chunkDefs));
    1290           1 :                 CPLPopErrorHandler();
    1291             :             }
    1292             :             {
    1293             :                 // array_start_idx[0] >= 3000
    1294           2 :                 std::vector<GUInt64> array_start_idx{3000, 0, 0};
    1295           2 :                 std::vector<GUInt64> count{1, 1000, 2000};
    1296           1 :                 CPLPushErrorHandler(CPLQuietErrorHandler);
    1297           1 :                 EXPECT_TRUE(!ar.ProcessPerChunk(array_start_idx.data(),
    1298             :                                                 count.data(), cs.data(),
    1299             :                                                 TmpStruct::func, &chunkDefs));
    1300           1 :                 CPLPopErrorHandler();
    1301             :             }
    1302             :             {
    1303             :                 // count[0] > 3000
    1304           2 :                 std::vector<GUInt64> array_start_idx{0, 0, 0};
    1305           2 :                 std::vector<GUInt64> count{3001, 1000, 2000};
    1306           1 :                 CPLPushErrorHandler(CPLQuietErrorHandler);
    1307           1 :                 EXPECT_TRUE(!ar.ProcessPerChunk(array_start_idx.data(),
    1308             :                                                 count.data(), cs.data(),
    1309             :                                                 TmpStruct::func, &chunkDefs));
    1310           1 :                 CPLPopErrorHandler();
    1311             :             }
    1312             :             {
    1313             :                 // count[0] == 0
    1314           2 :                 std::vector<GUInt64> array_start_idx{0, 0, 0};
    1315           2 :                 std::vector<GUInt64> count{0, 1000, 2000};
    1316           1 :                 CPLPushErrorHandler(CPLQuietErrorHandler);
    1317           1 :                 EXPECT_TRUE(!ar.ProcessPerChunk(array_start_idx.data(),
    1318             :                                                 count.data(), cs.data(),
    1319             :                                                 TmpStruct::func, &chunkDefs));
    1320           1 :                 CPLPopErrorHandler();
    1321             :             }
    1322             :             {
    1323             :                 // myCustomChunkSize[0] == 0
    1324           2 :                 std::vector<GUInt64> array_start_idx{0, 0, 0};
    1325           2 :                 std::vector<GUInt64> count{3000, 1000, 2000};
    1326           2 :                 std::vector<size_t> myCustomChunkSize{0, 1000, 2000};
    1327           1 :                 CPLPushErrorHandler(CPLQuietErrorHandler);
    1328           1 :                 EXPECT_TRUE(!ar.ProcessPerChunk(
    1329             :                     array_start_idx.data(), count.data(),
    1330             :                     myCustomChunkSize.data(), TmpStruct::func, &chunkDefs));
    1331           1 :                 CPLPopErrorHandler();
    1332             :             }
    1333             :             {
    1334             :                 // myCustomChunkSize[0] > 3000
    1335           2 :                 std::vector<GUInt64> array_start_idx{0, 0, 0};
    1336           2 :                 std::vector<GUInt64> count{3000, 1000, 2000};
    1337           2 :                 std::vector<size_t> myCustomChunkSize{3001, 1000, 2000};
    1338           1 :                 CPLPushErrorHandler(CPLQuietErrorHandler);
    1339           1 :                 EXPECT_TRUE(!ar.ProcessPerChunk(
    1340             :                     array_start_idx.data(), count.data(),
    1341             :                     myCustomChunkSize.data(), TmpStruct::func, &chunkDefs));
    1342           1 :                 CPLPopErrorHandler();
    1343             :             }
    1344             : 
    1345           2 :             std::vector<GUInt64> array_start_idx{1500, 256, 0};
    1346           2 :             std::vector<GUInt64> count{99, 512, 2000};
    1347           1 :             EXPECT_TRUE(ar.ProcessPerChunk(array_start_idx.data(), count.data(),
    1348             :                                            cs.data(), TmpStruct::func,
    1349             :                                            &chunkDefs));
    1350             : 
    1351           1 :             size_t nExpectedChunks = 1;
    1352           4 :             for (size_t i = 0; i < ar.GetDimensionCount(); i++)
    1353             :             {
    1354           3 :                 nExpectedChunks *= static_cast<size_t>(
    1355           3 :                     1 + ((array_start_idx[i] + count[i] - 1) / cs[i]) -
    1356           3 :                     (array_start_idx[i] / cs[i]));
    1357             :             }
    1358           1 :             EXPECT_EQ(chunkDefs.size(), nExpectedChunks);
    1359             : 
    1360           2 :             CPLString osChunks;
    1361           9 :             for (const auto &chunkDef : chunkDefs)
    1362             :             {
    1363             :                 osChunks += CPLSPrintf("{%u, %u, %u}, {%u, %u, %u}\n",
    1364           8 :                                        (unsigned)chunkDef.array_start_idx[0],
    1365           8 :                                        (unsigned)chunkDef.array_start_idx[1],
    1366           8 :                                        (unsigned)chunkDef.array_start_idx[2],
    1367           8 :                                        (unsigned)chunkDef.count[0],
    1368           8 :                                        (unsigned)chunkDef.count[1],
    1369           8 :                                        (unsigned)chunkDef.count[2]);
    1370             :             }
    1371           1 :             EXPECT_EQ(osChunks, "{1500, 256, 0}, {4, 256, 2000}\n"
    1372             :                                 "{1500, 512, 0}, {4, 256, 2000}\n"
    1373             :                                 "{1504, 256, 0}, {32, 256, 2000}\n"
    1374             :                                 "{1504, 512, 0}, {32, 256, 2000}\n"
    1375             :                                 "{1536, 256, 0}, {32, 256, 2000}\n"
    1376             :                                 "{1536, 512, 0}, {32, 256, 2000}\n"
    1377             :                                 "{1568, 256, 0}, {31, 256, 2000}\n"
    1378             :                                 "{1568, 512, 0}, {31, 256, 2000}\n");
    1379             :         }
    1380             :     }
    1381             : 
    1382             :     // Another error case of ProcessPerChunk
    1383             :     {
    1384           1 :         const auto M64 = std::numeric_limits<GUInt64>::max();
    1385           1 :         const auto Msize_t = std::numeric_limits<size_t>::max();
    1386           3 :         myArray ar(GDT_UInt16, {M64, M64, M64}, {32, 256, 128});
    1387             : 
    1388             :         // Product of myCustomChunkSize[] > Msize_t
    1389           2 :         std::vector<GUInt64> array_start_idx{0, 0, 0};
    1390           2 :         std::vector<GUInt64> count{3000, 1000, 2000};
    1391           2 :         std::vector<size_t> myCustomChunkSize{Msize_t, Msize_t, Msize_t};
    1392           2 :         std::vector<ChunkDef> chunkDefs;
    1393           1 :         CPLPushErrorHandler(CPLQuietErrorHandler);
    1394           1 :         EXPECT_TRUE(!ar.ProcessPerChunk(array_start_idx.data(), count.data(),
    1395             :                                         myCustomChunkSize.data(),
    1396             :                                         TmpStruct::func, &chunkDefs));
    1397           1 :         CPLPopErrorHandler();
    1398             :     }
    1399             : 
    1400             :     {
    1401           1 :         const auto BIG = GUInt64(5000) * 1000 * 1000;
    1402             :         myArray ar(GDT_UInt16, {BIG + 3000, BIG + 1000, BIG + 2000},
    1403           3 :                    {32, 256, 128});
    1404           2 :         std::vector<GUInt64> array_start_idx{BIG + 1500, BIG + 256, BIG + 0};
    1405           2 :         std::vector<GUInt64> count{99, 512, 2000};
    1406           2 :         std::vector<ChunkDef> chunkDefs;
    1407           2 :         auto cs = ar.GetProcessingChunkSize(40 * 1000 * 1000);
    1408           1 :         EXPECT_TRUE(ar.ProcessPerChunk(array_start_idx.data(), count.data(),
    1409             :                                        cs.data(), TmpStruct::func, &chunkDefs));
    1410             : 
    1411           1 :         size_t nExpectedChunks = 1;
    1412           4 :         for (size_t i = 0; i < ar.GetDimensionCount(); i++)
    1413             :         {
    1414           3 :             nExpectedChunks *= static_cast<size_t>(
    1415           3 :                 1 + ((array_start_idx[i] + count[i] - 1) / cs[i]) -
    1416           3 :                 (array_start_idx[i] / cs[i]));
    1417             :         }
    1418           1 :         EXPECT_EQ(chunkDefs.size(), nExpectedChunks);
    1419             : 
    1420           2 :         CPLString osChunks;
    1421           9 :         for (const auto &chunkDef : chunkDefs)
    1422             :         {
    1423             :             osChunks += CPLSPrintf("{" CPL_FRMT_GUIB ", " CPL_FRMT_GUIB
    1424             :                                    ", " CPL_FRMT_GUIB "}, {%u, %u, %u}\n",
    1425           8 :                                    (GUIntBig)chunkDef.array_start_idx[0],
    1426           8 :                                    (GUIntBig)chunkDef.array_start_idx[1],
    1427           8 :                                    (GUIntBig)chunkDef.array_start_idx[2],
    1428           8 :                                    (unsigned)chunkDef.count[0],
    1429           8 :                                    (unsigned)chunkDef.count[1],
    1430           8 :                                    (unsigned)chunkDef.count[2]);
    1431             :         }
    1432           1 :         EXPECT_EQ(osChunks,
    1433             :                   "{5000001500, 5000000256, 5000000000}, {4, 256, 2000}\n"
    1434             :                   "{5000001500, 5000000512, 5000000000}, {4, 256, 2000}\n"
    1435             :                   "{5000001504, 5000000256, 5000000000}, {32, 256, 2000}\n"
    1436             :                   "{5000001504, 5000000512, 5000000000}, {32, 256, 2000}\n"
    1437             :                   "{5000001536, 5000000256, 5000000000}, {32, 256, 2000}\n"
    1438             :                   "{5000001536, 5000000512, 5000000000}, {32, 256, 2000}\n"
    1439             :                   "{5000001568, 5000000256, 5000000000}, {31, 256, 2000}\n"
    1440             :                   "{5000001568, 5000000512, 5000000000}, {31, 256, 2000}\n");
    1441             :     }
    1442             : 
    1443             :     {
    1444             :         // Test with 0 in GetBlockSize()
    1445           3 :         myArray ar(GDT_UInt16, {500, 1000, 2000}, {0, 0, 128});
    1446             :         {
    1447           2 :             auto cs = ar.GetProcessingChunkSize(300 * 2);
    1448           1 :             EXPECT_EQ(cs.size(), 3U);
    1449           1 :             EXPECT_EQ(cs[0], 1U);
    1450           1 :             EXPECT_EQ(cs[1], 1U);
    1451           1 :             EXPECT_EQ(cs[2], 256U);
    1452             :         }
    1453             :         {
    1454           2 :             auto cs = ar.GetProcessingChunkSize(40 * 1000 * 1000);
    1455           1 :             EXPECT_EQ(cs.size(), 3U);
    1456           1 :             EXPECT_EQ(cs[0], 10U);
    1457           1 :             EXPECT_EQ(cs[1], 1000U);
    1458           1 :             EXPECT_EQ(cs[2], 2000U);
    1459             :         }
    1460             :         {
    1461           2 :             auto cs = ar.GetProcessingChunkSize(500U * 1000 * 2000 * 2);
    1462           1 :             EXPECT_EQ(cs.size(), 3U);
    1463           1 :             EXPECT_EQ(cs[0], 500U);
    1464           1 :             EXPECT_EQ(cs[1], 1000U);
    1465           1 :             EXPECT_EQ(cs[2], 2000U);
    1466             :         }
    1467             :         {
    1468           2 :             auto cs = ar.GetProcessingChunkSize(500U * 1000 * 2000 * 2 - 1);
    1469           1 :             EXPECT_EQ(cs.size(), 3U);
    1470           1 :             EXPECT_EQ(cs[0], 499U);
    1471           1 :             EXPECT_EQ(cs[1], 1000U);
    1472           1 :             EXPECT_EQ(cs[2], 2000U);
    1473             :         }
    1474             :     }
    1475             :     {
    1476           1 :         const auto M = std::numeric_limits<GUInt64>::max();
    1477           3 :         myArray ar(GDT_UInt16, {M, M, M}, {M, M, M / 2});
    1478             :         {
    1479           2 :             auto cs = ar.GetProcessingChunkSize(0);
    1480           1 :             EXPECT_EQ(cs.size(), 3U);
    1481           1 :             EXPECT_EQ(cs[0], 1U);
    1482           1 :             EXPECT_EQ(cs[1], 1U);
    1483             : #if SIZEOF_VOIDP == 8
    1484           1 :             EXPECT_EQ(cs[2], static_cast<size_t>(M / 2));
    1485             : #else
    1486             :             EXPECT_EQ(cs[2], 1U);
    1487             : #endif
    1488             :         }
    1489             :     }
    1490             : #if SIZEOF_VOIDP == 8
    1491             :     {
    1492           1 :         const auto M = std::numeric_limits<GUInt64>::max();
    1493           3 :         myArray ar(GDT_UInt16, {M, M, M}, {M, M, M / 4});
    1494             :         {
    1495             :             auto cs =
    1496           2 :                 ar.GetProcessingChunkSize(std::numeric_limits<size_t>::max());
    1497           1 :             EXPECT_EQ(cs.size(), 3U);
    1498           1 :             EXPECT_EQ(cs[0], 1U);
    1499           1 :             EXPECT_EQ(cs[1], 1U);
    1500           1 :             EXPECT_EQ(cs[2], (std::numeric_limits<size_t>::max() / 4) * 2);
    1501             :         }
    1502             :     }
    1503             : #endif
    1504           1 : }
    1505             : 
    1506             : // Test GDALDataset::GetRawBinaryLayout() implementations
    1507           4 : TEST_F(test_gdal, GetRawBinaryLayout_ENVI)
    1508             : {
    1509           1 :     if (GDALGetDriverByName("ENVI") == nullptr)
    1510             :     {
    1511           0 :         GTEST_SKIP() << "ENVI driver missing";
    1512             :     }
    1513             : 
    1514             :     {
    1515             :         GDALDatasetUniquePtr poDS(
    1516           2 :             GDALDataset::Open(GDRIVERS_DATA_DIR "envi/envi_rgbsmall_bip.img"));
    1517           1 :         EXPECT_TRUE(poDS != nullptr);
    1518           2 :         GDALDataset::RawBinaryLayout sLayout;
    1519           1 :         EXPECT_TRUE(poDS->GetRawBinaryLayout(sLayout));
    1520           1 :         EXPECT_EQ(sLayout.osRawFilename, poDS->GetDescription());
    1521           1 :         EXPECT_EQ(
    1522             :             static_cast<int>(sLayout.eInterleaving),
    1523             :             static_cast<int>(GDALDataset::RawBinaryLayout::Interleaving::BIP));
    1524           1 :         EXPECT_EQ(sLayout.eDataType, GDT_Byte);
    1525           1 :         EXPECT_TRUE(sLayout.bLittleEndianOrder);
    1526           1 :         EXPECT_EQ(sLayout.nImageOffset, 0U);
    1527           1 :         EXPECT_EQ(sLayout.nPixelOffset, 3);
    1528           1 :         EXPECT_EQ(sLayout.nLineOffset, 3 * 50);
    1529           1 :         EXPECT_EQ(sLayout.nBandOffset, 1);
    1530             :     }
    1531             : 
    1532             :     {
    1533             :         GDALDatasetUniquePtr poDS(
    1534           2 :             GDALDataset::Open(GDRIVERS_DATA_DIR "envi/envi_rgbsmall_bil.img"));
    1535           1 :         EXPECT_TRUE(poDS != nullptr);
    1536           2 :         GDALDataset::RawBinaryLayout sLayout;
    1537           1 :         EXPECT_TRUE(poDS->GetRawBinaryLayout(sLayout));
    1538           1 :         EXPECT_EQ(sLayout.osRawFilename, poDS->GetDescription());
    1539           1 :         EXPECT_EQ(
    1540             :             static_cast<int>(sLayout.eInterleaving),
    1541             :             static_cast<int>(GDALDataset::RawBinaryLayout::Interleaving::BIL));
    1542           1 :         EXPECT_EQ(sLayout.eDataType, GDT_Byte);
    1543           1 :         EXPECT_TRUE(sLayout.bLittleEndianOrder);
    1544           1 :         EXPECT_EQ(sLayout.nImageOffset, 0U);
    1545           1 :         EXPECT_EQ(sLayout.nPixelOffset, 1);
    1546           1 :         EXPECT_EQ(sLayout.nLineOffset, 3 * 50);
    1547           1 :         EXPECT_EQ(sLayout.nBandOffset, 50);
    1548             :     }
    1549             : 
    1550             :     {
    1551             :         GDALDatasetUniquePtr poDS(
    1552           2 :             GDALDataset::Open(GDRIVERS_DATA_DIR "envi/envi_rgbsmall_bsq.img"));
    1553           1 :         EXPECT_TRUE(poDS != nullptr);
    1554           2 :         GDALDataset::RawBinaryLayout sLayout;
    1555           1 :         EXPECT_TRUE(poDS->GetRawBinaryLayout(sLayout));
    1556           1 :         EXPECT_EQ(sLayout.osRawFilename, poDS->GetDescription());
    1557           1 :         EXPECT_EQ(
    1558             :             static_cast<int>(sLayout.eInterleaving),
    1559             :             static_cast<int>(GDALDataset::RawBinaryLayout::Interleaving::BSQ));
    1560           1 :         EXPECT_EQ(sLayout.eDataType, GDT_Byte);
    1561           1 :         EXPECT_TRUE(sLayout.bLittleEndianOrder);
    1562           1 :         EXPECT_EQ(sLayout.nImageOffset, 0U);
    1563           1 :         EXPECT_EQ(sLayout.nPixelOffset, 1);
    1564           1 :         EXPECT_EQ(sLayout.nLineOffset, 50);
    1565           1 :         EXPECT_EQ(sLayout.nBandOffset, 50 * 49);
    1566             :     }
    1567             : }
    1568             : 
    1569             : // Test GDALDataset::GetRawBinaryLayout() implementations
    1570           4 : TEST_F(test_gdal, GetRawBinaryLayout_GTIFF)
    1571             : {
    1572           1 :     if (GDALGetDriverByName("GTIFF") == nullptr)
    1573             :     {
    1574           0 :         GTEST_SKIP() << "GTIFF driver missing";
    1575             :     }
    1576             : 
    1577             :     {
    1578             :         GDALDatasetUniquePtr poDS(
    1579           2 :             GDALDataset::Open(GCORE_DATA_DIR "uint16.tif"));
    1580           1 :         EXPECT_TRUE(poDS != nullptr);
    1581           2 :         GDALDataset::RawBinaryLayout sLayout;
    1582           1 :         EXPECT_TRUE(poDS->GetRawBinaryLayout(sLayout));
    1583           1 :         EXPECT_EQ(sLayout.osRawFilename, poDS->GetDescription());
    1584           1 :         EXPECT_EQ(static_cast<int>(sLayout.eInterleaving),
    1585             :                   static_cast<int>(
    1586             :                       GDALDataset::RawBinaryLayout::Interleaving::UNKNOWN));
    1587           1 :         EXPECT_EQ(sLayout.eDataType, GDT_UInt16);
    1588           1 :         EXPECT_TRUE(sLayout.bLittleEndianOrder);
    1589           1 :         EXPECT_EQ(sLayout.nImageOffset, 8U);
    1590           1 :         EXPECT_EQ(sLayout.nPixelOffset, 2);
    1591           1 :         EXPECT_EQ(sLayout.nLineOffset, 40);
    1592           1 :         EXPECT_EQ(sLayout.nBandOffset, 0);
    1593             :     }
    1594             : 
    1595             :     {
    1596             :         GDALDatasetUniquePtr poDS(
    1597           2 :             GDALDataset::Open(GCORE_DATA_DIR "rgbsmall.tif"));
    1598           1 :         EXPECT_TRUE(poDS != nullptr);
    1599           2 :         GDALDataset::RawBinaryLayout sLayout;
    1600             :         // Compressed
    1601           1 :         EXPECT_TRUE(!poDS->GetRawBinaryLayout(sLayout));
    1602             :     }
    1603             : 
    1604             :     {
    1605             :         GDALDatasetUniquePtr poDS(
    1606           2 :             GDALDataset::Open(GCORE_DATA_DIR "stefan_full_rgba.tif"));
    1607           1 :         EXPECT_TRUE(poDS != nullptr);
    1608           2 :         GDALDataset::RawBinaryLayout sLayout;
    1609           1 :         EXPECT_TRUE(poDS->GetRawBinaryLayout(sLayout));
    1610           1 :         EXPECT_EQ(sLayout.osRawFilename, poDS->GetDescription());
    1611           1 :         EXPECT_EQ(
    1612             :             static_cast<int>(sLayout.eInterleaving),
    1613             :             static_cast<int>(GDALDataset::RawBinaryLayout::Interleaving::BIP));
    1614           1 :         EXPECT_EQ(sLayout.eDataType, GDT_Byte);
    1615           1 :         EXPECT_EQ(sLayout.nImageOffset, 278U);
    1616           1 :         EXPECT_EQ(sLayout.nPixelOffset, 4);
    1617           1 :         EXPECT_EQ(sLayout.nLineOffset, 162 * 4);
    1618           1 :         EXPECT_EQ(sLayout.nBandOffset, 1);
    1619             :     }
    1620             : 
    1621             :     {
    1622             :         GDALDatasetUniquePtr poSrcDS(
    1623           2 :             GDALDataset::Open(GCORE_DATA_DIR "rgbsmall.tif"));
    1624           1 :         EXPECT_TRUE(poSrcDS != nullptr);
    1625           1 :         auto tmpFilename = "/vsimem/tmp.tif";
    1626           1 :         auto poDrv = GDALDriver::FromHandle(GDALGetDriverByName("GTiff"));
    1627           1 :         const char *options[] = {"INTERLEAVE=BAND", nullptr};
    1628             :         auto poDS(GDALDatasetUniquePtr(
    1629             :             poDrv->CreateCopy(tmpFilename, poSrcDS.get(), false,
    1630           2 :                               const_cast<char **>(options), nullptr, nullptr)));
    1631           1 :         EXPECT_TRUE(poDS != nullptr);
    1632           2 :         GDALDataset::RawBinaryLayout sLayout;
    1633           1 :         EXPECT_TRUE(poDS->GetRawBinaryLayout(sLayout));
    1634           1 :         EXPECT_EQ(sLayout.osRawFilename, poDS->GetDescription());
    1635           1 :         EXPECT_EQ(
    1636             :             static_cast<int>(sLayout.eInterleaving),
    1637             :             static_cast<int>(GDALDataset::RawBinaryLayout::Interleaving::BSQ));
    1638           1 :         EXPECT_EQ(sLayout.eDataType, GDT_Byte);
    1639           1 :         EXPECT_TRUE(sLayout.nImageOffset >= 396U);
    1640           1 :         EXPECT_EQ(sLayout.nPixelOffset, 1);
    1641           1 :         EXPECT_EQ(sLayout.nLineOffset, 50);
    1642           1 :         EXPECT_EQ(sLayout.nBandOffset, 50 * 50);
    1643           1 :         poDS.reset();
    1644           1 :         VSIUnlink(tmpFilename);
    1645             :     }
    1646             : 
    1647             :     {
    1648             :         GDALDatasetUniquePtr poSrcDS(
    1649           2 :             GDALDataset::Open(GCORE_DATA_DIR "rgbsmall.tif"));
    1650           1 :         EXPECT_TRUE(poSrcDS != nullptr);
    1651           1 :         auto tmpFilename = "/vsimem/tmp.tif";
    1652           1 :         const char *options[] = {"-srcwin",
    1653             :                                  "0",
    1654             :                                  "0",
    1655             :                                  "48",
    1656             :                                  "32",
    1657             :                                  "-co",
    1658             :                                  "INTERLEAVE=PIXEL",
    1659             :                                  "-co",
    1660             :                                  "TILED=YES",
    1661             :                                  "-co",
    1662             :                                  "BLOCKXSIZE=48",
    1663             :                                  "-co",
    1664             :                                  "BLOCKYSIZE=32",
    1665             :                                  nullptr};
    1666             :         auto psOptions =
    1667           1 :             GDALTranslateOptionsNew(const_cast<char **>(options), nullptr);
    1668             :         auto poDS(GDALDatasetUniquePtr(GDALDataset::FromHandle(
    1669             :             GDALTranslate(tmpFilename, GDALDataset::ToHandle(poSrcDS.get()),
    1670           2 :                           psOptions, nullptr))));
    1671           1 :         GDALTranslateOptionsFree(psOptions);
    1672           1 :         EXPECT_TRUE(poDS != nullptr);
    1673           2 :         GDALDataset::RawBinaryLayout sLayout;
    1674           1 :         EXPECT_TRUE(poDS->GetRawBinaryLayout(sLayout));
    1675           1 :         EXPECT_EQ(sLayout.osRawFilename, poDS->GetDescription());
    1676           1 :         EXPECT_EQ(
    1677             :             static_cast<int>(sLayout.eInterleaving),
    1678             :             static_cast<int>(GDALDataset::RawBinaryLayout::Interleaving::BIP));
    1679           1 :         EXPECT_EQ(sLayout.eDataType, GDT_Byte);
    1680           1 :         EXPECT_TRUE(sLayout.nImageOffset >= 390U);
    1681           1 :         EXPECT_EQ(sLayout.nPixelOffset, 3);
    1682           1 :         EXPECT_EQ(sLayout.nLineOffset, 48 * 3);
    1683           1 :         EXPECT_EQ(sLayout.nBandOffset, 1);
    1684           1 :         poDS.reset();
    1685           1 :         VSIUnlink(tmpFilename);
    1686             :     }
    1687             : 
    1688             :     {
    1689             :         GDALDatasetUniquePtr poSrcDS(
    1690           2 :             GDALDataset::Open(GCORE_DATA_DIR "rgbsmall.tif"));
    1691           1 :         EXPECT_TRUE(poSrcDS != nullptr);
    1692           1 :         auto tmpFilename = "/vsimem/tmp.tif";
    1693           1 :         const char *options[] = {"-srcwin",
    1694             :                                  "0",
    1695             :                                  "0",
    1696             :                                  "48",
    1697             :                                  "32",
    1698             :                                  "-ot",
    1699             :                                  "UInt16",
    1700             :                                  "-co",
    1701             :                                  "TILED=YES",
    1702             :                                  "-co",
    1703             :                                  "BLOCKXSIZE=48",
    1704             :                                  "-co",
    1705             :                                  "BLOCKYSIZE=32",
    1706             :                                  "-co",
    1707             :                                  "INTERLEAVE=BAND",
    1708             :                                  "-co",
    1709             :                                  "ENDIANNESS=BIG",
    1710             :                                  nullptr};
    1711             :         auto psOptions =
    1712           1 :             GDALTranslateOptionsNew(const_cast<char **>(options), nullptr);
    1713             :         auto poDS(GDALDatasetUniquePtr(GDALDataset::FromHandle(
    1714             :             GDALTranslate(tmpFilename, GDALDataset::ToHandle(poSrcDS.get()),
    1715           2 :                           psOptions, nullptr))));
    1716           1 :         GDALTranslateOptionsFree(psOptions);
    1717           1 :         EXPECT_TRUE(poDS != nullptr);
    1718           2 :         GDALDataset::RawBinaryLayout sLayout;
    1719           1 :         EXPECT_TRUE(poDS->GetRawBinaryLayout(sLayout));
    1720           1 :         EXPECT_EQ(sLayout.osRawFilename, poDS->GetDescription());
    1721           1 :         EXPECT_EQ(
    1722             :             static_cast<int>(sLayout.eInterleaving),
    1723             :             static_cast<int>(GDALDataset::RawBinaryLayout::Interleaving::BSQ));
    1724           1 :         EXPECT_EQ(sLayout.eDataType, GDT_UInt16);
    1725           1 :         EXPECT_TRUE(!sLayout.bLittleEndianOrder);
    1726           1 :         EXPECT_TRUE(sLayout.nImageOffset >= 408U);
    1727           1 :         EXPECT_EQ(sLayout.nPixelOffset, 2);
    1728           1 :         EXPECT_EQ(sLayout.nLineOffset, 2 * 48);
    1729           1 :         EXPECT_EQ(sLayout.nBandOffset, 2 * 48 * 32);
    1730           1 :         poDS.reset();
    1731           1 :         VSIUnlink(tmpFilename);
    1732             :     }
    1733             : }
    1734             : 
    1735             : // Test GDALDataset::GetRawBinaryLayout() implementations
    1736           4 : TEST_F(test_gdal, GetRawBinaryLayout_ISIS3)
    1737             : {
    1738           1 :     if (GDALGetDriverByName("ISIS3") == nullptr)
    1739             :     {
    1740           0 :         GTEST_SKIP() << "ISIS3 driver missing";
    1741             :     }
    1742             : 
    1743             :     {
    1744             :         GDALDatasetUniquePtr poDS(
    1745           2 :             GDALDataset::Open(GDRIVERS_DATA_DIR "isis3/isis3_detached.lbl"));
    1746           1 :         EXPECT_TRUE(poDS != nullptr);
    1747           2 :         GDALDataset::RawBinaryLayout sLayout;
    1748           1 :         EXPECT_TRUE(poDS->GetRawBinaryLayout(sLayout));
    1749           1 :         EXPECT_TRUE(sLayout.osRawFilename.find("isis3_detached.cub") !=
    1750             :                     std::string::npos);
    1751           1 :         EXPECT_EQ(static_cast<int>(sLayout.eInterleaving),
    1752             :                   static_cast<int>(
    1753             :                       GDALDataset::RawBinaryLayout::Interleaving::UNKNOWN));
    1754           1 :         EXPECT_EQ(sLayout.eDataType, GDT_Byte);
    1755           1 :         EXPECT_TRUE(sLayout.bLittleEndianOrder);
    1756           1 :         EXPECT_EQ(sLayout.nImageOffset, 0U);
    1757           1 :         EXPECT_EQ(sLayout.nPixelOffset, 1);
    1758           1 :         EXPECT_EQ(sLayout.nLineOffset, 317);
    1759             :         // EXPECT_EQ( sLayout.nBandOffset, 9510 ); // doesn't matter on single
    1760             :         // band
    1761             :     }
    1762             : }
    1763             : 
    1764             : // Test GDALDataset::GetRawBinaryLayout() implementations
    1765           4 : TEST_F(test_gdal, GetRawBinaryLayout_VICAR)
    1766             : {
    1767           1 :     if (GDALGetDriverByName("VICAR") == nullptr)
    1768             :     {
    1769           0 :         GTEST_SKIP() << "VICAR driver missing";
    1770             :     }
    1771             : 
    1772             :     {
    1773             :         GDALDatasetUniquePtr poDS(GDALDataset::Open(
    1774           2 :             GDRIVERS_DATA_DIR "vicar/test_vicar_truncated.bin"));
    1775           1 :         EXPECT_TRUE(poDS != nullptr);
    1776           2 :         GDALDataset::RawBinaryLayout sLayout;
    1777           1 :         EXPECT_TRUE(poDS->GetRawBinaryLayout(sLayout));
    1778           1 :         EXPECT_EQ(sLayout.osRawFilename, poDS->GetDescription());
    1779           1 :         EXPECT_EQ(static_cast<int>(sLayout.eInterleaving),
    1780             :                   static_cast<int>(
    1781             :                       GDALDataset::RawBinaryLayout::Interleaving::UNKNOWN));
    1782           1 :         EXPECT_EQ(sLayout.eDataType, GDT_Byte);
    1783           1 :         EXPECT_TRUE(sLayout.bLittleEndianOrder);
    1784           1 :         EXPECT_EQ(sLayout.nImageOffset, 9680U);
    1785           1 :         EXPECT_EQ(sLayout.nPixelOffset, 1);
    1786           1 :         EXPECT_EQ(sLayout.nLineOffset, 400);
    1787           1 :         EXPECT_EQ(sLayout.nBandOffset, 0);  // doesn't matter on single band
    1788             :     }
    1789             : }
    1790             : 
    1791             : // Test GDALDataset::GetRawBinaryLayout() implementations
    1792           4 : TEST_F(test_gdal, GetRawBinaryLayout_FITS)
    1793             : {
    1794           1 :     if (GDALGetDriverByName("FITS") == nullptr)
    1795             :     {
    1796           0 :         GTEST_SKIP() << "FITS driver missing";
    1797             :     }
    1798             : 
    1799             :     {
    1800             :         GDALDatasetUniquePtr poSrcDS(
    1801           2 :             GDALDataset::Open(GCORE_DATA_DIR "int16.tif"));
    1802           1 :         EXPECT_TRUE(poSrcDS != nullptr);
    1803           2 :         CPLString tmpFilename(CPLGenerateTempFilename(nullptr));
    1804           1 :         tmpFilename += ".fits";
    1805           1 :         auto poDrv = GDALDriver::FromHandle(GDALGetDriverByName("FITS"));
    1806           1 :         if (poDrv)
    1807             :         {
    1808             :             auto poDS(GDALDatasetUniquePtr(poDrv->CreateCopy(
    1809           2 :                 tmpFilename, poSrcDS.get(), false, nullptr, nullptr, nullptr)));
    1810           1 :             EXPECT_TRUE(poDS != nullptr);
    1811           1 :             poDS.reset();
    1812           1 :             poDS.reset(GDALDataset::Open(tmpFilename));
    1813           1 :             EXPECT_TRUE(poDS != nullptr);
    1814           2 :             GDALDataset::RawBinaryLayout sLayout;
    1815           1 :             EXPECT_TRUE(poDS->GetRawBinaryLayout(sLayout));
    1816           1 :             EXPECT_EQ(sLayout.osRawFilename, poDS->GetDescription());
    1817           1 :             EXPECT_EQ(static_cast<int>(sLayout.eInterleaving),
    1818             :                       static_cast<int>(
    1819             :                           GDALDataset::RawBinaryLayout::Interleaving::UNKNOWN));
    1820           1 :             EXPECT_EQ(sLayout.eDataType, GDT_Int16);
    1821           1 :             EXPECT_TRUE(!sLayout.bLittleEndianOrder);
    1822           1 :             EXPECT_EQ(sLayout.nImageOffset, 2880U);
    1823           1 :             EXPECT_EQ(sLayout.nPixelOffset, 2);
    1824           1 :             EXPECT_EQ(sLayout.nLineOffset, 2 * 20);
    1825           1 :             EXPECT_EQ(sLayout.nBandOffset, 2 * 20 * 20);
    1826           1 :             poDS.reset();
    1827           1 :             VSIUnlink(tmpFilename);
    1828             :         }
    1829             :     }
    1830             : }
    1831             : 
    1832             : // Test GDALDataset::GetRawBinaryLayout() implementations
    1833           4 : TEST_F(test_gdal, GetRawBinaryLayout_PDS)
    1834             : {
    1835           1 :     if (GDALGetDriverByName("PDS") == nullptr)
    1836             :     {
    1837           0 :         GTEST_SKIP() << "PDS driver missing";
    1838             :     }
    1839             : 
    1840             :     {
    1841             :         GDALDatasetUniquePtr poDS(
    1842           2 :             GDALDataset::Open(GDRIVERS_DATA_DIR "pds/mc02_truncated.img"));
    1843           1 :         EXPECT_TRUE(poDS != nullptr);
    1844           2 :         GDALDataset::RawBinaryLayout sLayout;
    1845           1 :         EXPECT_TRUE(poDS->GetRawBinaryLayout(sLayout));
    1846           1 :         EXPECT_EQ(sLayout.osRawFilename, poDS->GetDescription());
    1847           1 :         EXPECT_EQ(static_cast<int>(sLayout.eInterleaving),
    1848             :                   static_cast<int>(
    1849             :                       GDALDataset::RawBinaryLayout::Interleaving::UNKNOWN));
    1850           1 :         EXPECT_EQ(sLayout.eDataType, GDT_Byte);
    1851           1 :         EXPECT_TRUE(sLayout.bLittleEndianOrder);
    1852           1 :         EXPECT_EQ(sLayout.nImageOffset, 3840U);
    1853           1 :         EXPECT_EQ(sLayout.nPixelOffset, 1);
    1854           1 :         EXPECT_EQ(sLayout.nLineOffset, 3840);
    1855           1 :         EXPECT_EQ(sLayout.nBandOffset, 0);  // doesn't matter on single band
    1856             :     }
    1857             : }
    1858             : 
    1859             : // Test GDALDataset::GetRawBinaryLayout() implementations
    1860           4 : TEST_F(test_gdal, GetRawBinaryLayout_PDS4)
    1861             : {
    1862           1 :     if (GDALGetDriverByName("PDS4") == nullptr)
    1863             :     {
    1864           0 :         GTEST_SKIP() << "PDS4 driver missing";
    1865             :     }
    1866             : 
    1867             :     {
    1868             :         GDALDatasetUniquePtr poDS(GDALDataset::Open(
    1869           2 :             GDRIVERS_DATA_DIR "pds4/byte_pds4_cart_1700.xml"));
    1870           1 :         EXPECT_TRUE(poDS != nullptr);
    1871           2 :         GDALDataset::RawBinaryLayout sLayout;
    1872           1 :         EXPECT_TRUE(poDS->GetRawBinaryLayout(sLayout));
    1873           1 :         EXPECT_TRUE(sLayout.osRawFilename.find("byte_pds4_cart_1700.img") !=
    1874             :                     std::string::npos);
    1875           1 :         EXPECT_EQ(static_cast<int>(sLayout.eInterleaving),
    1876             :                   static_cast<int>(
    1877             :                       GDALDataset::RawBinaryLayout::Interleaving::UNKNOWN));
    1878           1 :         EXPECT_EQ(sLayout.eDataType, GDT_Byte);
    1879           1 :         EXPECT_TRUE(!sLayout.bLittleEndianOrder);
    1880           1 :         EXPECT_EQ(sLayout.nImageOffset, 0U);
    1881           1 :         EXPECT_EQ(sLayout.nPixelOffset, 1);
    1882           1 :         EXPECT_EQ(sLayout.nLineOffset, 20);
    1883           1 :         EXPECT_EQ(sLayout.nBandOffset, 0);  // doesn't matter on single band
    1884             :     }
    1885             : }
    1886             : 
    1887             : // Test TileMatrixSet
    1888           4 : TEST_F(test_gdal, TileMatrixSet)
    1889             : {
    1890           1 :     if (getenv("SKIP_TILEMATRIXSET_TEST") != nullptr)
    1891           0 :         GTEST_SKIP() << "Test skipped due to SKIP_TILEMATRIXSET_TEST being set";
    1892             : 
    1893             :     {
    1894           2 :         auto l = gdal::TileMatrixSet::listPredefinedTileMatrixSets();
    1895           1 :         EXPECT_TRUE(l.find("GoogleMapsCompatible") != l.end());
    1896           1 :         EXPECT_TRUE(l.find("NZTM2000") != l.end());
    1897             :     }
    1898             : 
    1899             :     {
    1900           1 :         CPLPushErrorHandler(CPLQuietErrorHandler);
    1901           1 :         EXPECT_TRUE(gdal::TileMatrixSet::parse("i_dont_exist") == nullptr);
    1902           1 :         CPLPopErrorHandler();
    1903             :     }
    1904             : 
    1905             :     {
    1906           1 :         CPLErrorReset();
    1907           1 :         CPLPushErrorHandler(CPLQuietErrorHandler);
    1908             :         // Invalid JSON
    1909           1 :         EXPECT_TRUE(gdal::TileMatrixSet::parse(
    1910             :                         "http://127.0.0.1:32767/example.json") == nullptr);
    1911           1 :         CPLPopErrorHandler();
    1912           1 :         EXPECT_TRUE(CPLGetLastErrorType() != 0);
    1913             :     }
    1914             : 
    1915             :     {
    1916           1 :         CPLPushErrorHandler(CPLQuietErrorHandler);
    1917             :         // Invalid JSON
    1918           1 :         EXPECT_TRUE(gdal::TileMatrixSet::parse(
    1919             :                         "{\"type\": \"TileMatrixSetType\" invalid") == nullptr);
    1920           1 :         CPLPopErrorHandler();
    1921             :     }
    1922             : 
    1923             :     {
    1924           1 :         CPLPushErrorHandler(CPLQuietErrorHandler);
    1925             :         // No tileMatrix
    1926           1 :         EXPECT_TRUE(gdal::TileMatrixSet::parse(
    1927             :                         "{\"type\": \"TileMatrixSetType\" }") == nullptr);
    1928           1 :         CPLPopErrorHandler();
    1929             :     }
    1930             : 
    1931             :     {
    1932           2 :         auto poTMS = gdal::TileMatrixSet::parse("LINZAntarticaMapTileGrid");
    1933           1 :         EXPECT_TRUE(poTMS != nullptr);
    1934           1 :         if (poTMS)
    1935             :         {
    1936           1 :             EXPECT_TRUE(poTMS->haveAllLevelsSameTopLeft());
    1937           1 :             EXPECT_TRUE(poTMS->haveAllLevelsSameTileSize());
    1938           1 :             EXPECT_TRUE(poTMS->hasOnlyPowerOfTwoVaryingScales());
    1939           1 :             EXPECT_TRUE(!poTMS->hasVariableMatrixWidth());
    1940             :         }
    1941             :     }
    1942             : 
    1943             :     {
    1944           2 :         auto poTMS = gdal::TileMatrixSet::parse("NZTM2000");
    1945           1 :         EXPECT_TRUE(poTMS != nullptr);
    1946           1 :         if (poTMS)
    1947             :         {
    1948           1 :             EXPECT_TRUE(poTMS->haveAllLevelsSameTopLeft());
    1949           1 :             EXPECT_TRUE(poTMS->haveAllLevelsSameTileSize());
    1950           1 :             EXPECT_TRUE(!poTMS->hasOnlyPowerOfTwoVaryingScales());
    1951           1 :             EXPECT_TRUE(!poTMS->hasVariableMatrixWidth());
    1952             :         }
    1953             :     }
    1954             : 
    1955             :     // Inline JSON with minimal structure
    1956             :     {
    1957             :         auto poTMS = gdal::TileMatrixSet::parse(
    1958             :             "{\"type\": \"TileMatrixSetType\", \"supportedCRS\": "
    1959             :             "\"http://www.opengis.net/def/crs/OGC/1.3/CRS84\", \"tileMatrix\": "
    1960           2 :             "[{ \"topLeftCorner\": [-180, 90],\"scaleDenominator\":1.0}] }");
    1961           1 :         EXPECT_TRUE(poTMS != nullptr);
    1962           1 :         if (poTMS)
    1963             :         {
    1964           1 :             EXPECT_TRUE(poTMS->haveAllLevelsSameTopLeft());
    1965           1 :             EXPECT_TRUE(poTMS->haveAllLevelsSameTileSize());
    1966           1 :             EXPECT_TRUE(poTMS->hasOnlyPowerOfTwoVaryingScales());
    1967           1 :             EXPECT_TRUE(!poTMS->hasVariableMatrixWidth());
    1968             :         }
    1969             :     }
    1970             : 
    1971             :     // Invalid scaleDenominator
    1972             :     {
    1973           1 :         CPLPushErrorHandler(CPLQuietErrorHandler);
    1974           1 :         EXPECT_TRUE(gdal::TileMatrixSet::parse(
    1975             :                         "{\"type\": \"TileMatrixSetType\", \"supportedCRS\": "
    1976             :                         "\"http://www.opengis.net/def/crs/OGC/1.3/CRS84\", "
    1977             :                         "\"tileMatrix\": [{ \"topLeftCorner\": [-180, "
    1978             :                         "90],\"scaleDenominator\":0.0}] }") == nullptr);
    1979           1 :         CPLPopErrorHandler();
    1980             :     }
    1981             : 
    1982             :     {
    1983           1 :         const char *pszJSON = "{"
    1984             :                               "    \"type\": \"TileMatrixSetType\","
    1985             :                               "    \"title\": \"CRS84 for the World\","
    1986             :                               "    \"identifier\": \"WorldCRS84Quad\","
    1987             :                               "    \"abstract\": \"my abstract\","
    1988             :                               "    \"boundingBox\":"
    1989             :                               "    {"
    1990             :                               "        \"type\": \"BoundingBoxType\","
    1991             :                               "        \"crs\": "
    1992             :                               "\"http://www.opengis.net/def/crs/OGC/1.X/"
    1993             :                               "CRS84\","  // 1.3 modified to 1.X to test
    1994             :                                           // difference with supportedCRS
    1995             :                               "        \"lowerCorner\": [-180, -90],"
    1996             :                               "        \"upperCorner\": [180, 90]"
    1997             :                               "    },"
    1998             :                               "    \"supportedCRS\": "
    1999             :                               "\"http://www.opengis.net/def/crs/OGC/1.3/"
    2000             :                               "CRS84\","
    2001             :                               "    \"wellKnownScaleSet\": "
    2002             :                               "\"http://www.opengis.net/def/wkss/OGC/1.0/"
    2003             :                               "GoogleCRS84Quad\","
    2004             :                               "    \"tileMatrix\":"
    2005             :                               "    ["
    2006             :                               "        {"
    2007             :                               "            \"type\": \"TileMatrixType\","
    2008             :                               "            \"identifier\": \"0\","
    2009             :                               "            \"scaleDenominator\": "
    2010             :                               "279541132.014358,"
    2011             :                               "            \"topLeftCorner\": [-180, 90],"
    2012             :                               "            \"tileWidth\": 256,"
    2013             :                               "            \"tileHeight\": 256,"
    2014             :                               "            \"matrixWidth\": 2,"
    2015             :                               "            \"matrixHeight\": 1"
    2016             :                               "        },"
    2017             :                               "        {"
    2018             :                               "            \"type\": \"TileMatrixType\","
    2019             :                               "            \"identifier\": \"1\","
    2020             :                               "            \"scaleDenominator\": "
    2021             :                               "139770566.007179,"
    2022             :                               "            \"topLeftCorner\": [-180, 90],"
    2023             :                               "            \"tileWidth\": 256,"
    2024             :                               "            \"tileHeight\": 256,"
    2025             :                               "            \"matrixWidth\": 4,"
    2026             :                               "            \"matrixHeight\": 2"
    2027             :                               "        }"
    2028             :                               "    ]"
    2029             :                               "}";
    2030           1 :         VSIFCloseL(VSIFileFromMemBuffer(
    2031             :             "/vsimem/tmp.json",
    2032             :             reinterpret_cast<GByte *>(const_cast<char *>(pszJSON)),
    2033           1 :             strlen(pszJSON), false));
    2034           1 :         auto poTMS = gdal::TileMatrixSet::parse("/vsimem/tmp.json");
    2035           1 :         VSIUnlink("/vsimem/tmp.json");
    2036             : 
    2037           1 :         EXPECT_TRUE(poTMS != nullptr);
    2038           1 :         if (poTMS)
    2039             :         {
    2040           1 :             EXPECT_EQ(poTMS->title(), "CRS84 for the World");
    2041           1 :             EXPECT_EQ(poTMS->identifier(), "WorldCRS84Quad");
    2042           1 :             EXPECT_EQ(poTMS->abstract(), "my abstract");
    2043           1 :             EXPECT_EQ(poTMS->crs(),
    2044             :                       "http://www.opengis.net/def/crs/OGC/1.3/CRS84");
    2045           1 :             EXPECT_EQ(
    2046             :                 poTMS->wellKnownScaleSet(),
    2047             :                 "http://www.opengis.net/def/wkss/OGC/1.0/GoogleCRS84Quad");
    2048           1 :             EXPECT_EQ(poTMS->bbox().mCrs,
    2049             :                       "http://www.opengis.net/def/crs/OGC/1.X/CRS84");
    2050           1 :             EXPECT_EQ(poTMS->bbox().mLowerCornerX, -180.0);
    2051           1 :             EXPECT_EQ(poTMS->bbox().mLowerCornerY, -90.0);
    2052           1 :             EXPECT_EQ(poTMS->bbox().mUpperCornerX, 180.0);
    2053           1 :             EXPECT_EQ(poTMS->bbox().mUpperCornerY, 90.0);
    2054           1 :             ASSERT_EQ(poTMS->tileMatrixList().size(), 2U);
    2055           1 :             EXPECT_TRUE(poTMS->haveAllLevelsSameTopLeft());
    2056           1 :             EXPECT_TRUE(poTMS->haveAllLevelsSameTileSize());
    2057           1 :             EXPECT_TRUE(poTMS->hasOnlyPowerOfTwoVaryingScales());
    2058           1 :             EXPECT_TRUE(!poTMS->hasVariableMatrixWidth());
    2059           1 :             const auto &tm = poTMS->tileMatrixList()[0];
    2060           1 :             EXPECT_EQ(tm.mId, "0");
    2061           1 :             EXPECT_EQ(tm.mScaleDenominator, 279541132.014358);
    2062           1 :             EXPECT_TRUE(fabs(tm.mResX - tm.mScaleDenominator * 0.28e-3 /
    2063             :                                             (6378137. * M_PI / 180)) < 1e-10);
    2064           1 :             EXPECT_TRUE(fabs(tm.mResX - 180. / 256) < 1e-10);
    2065           1 :             EXPECT_EQ(tm.mResY, tm.mResX);
    2066           1 :             EXPECT_EQ(tm.mTopLeftX, -180.0);
    2067           1 :             EXPECT_EQ(tm.mTopLeftY, 90.0);
    2068           1 :             EXPECT_EQ(tm.mTileWidth, 256);
    2069           1 :             EXPECT_EQ(tm.mTileHeight, 256);
    2070           1 :             EXPECT_EQ(tm.mMatrixWidth, 2);
    2071           1 :             EXPECT_EQ(tm.mMatrixHeight, 1);
    2072             :         }
    2073             :     }
    2074             : 
    2075             :     {
    2076             :         auto poTMS = gdal::TileMatrixSet::parse(
    2077             :             "{"
    2078             :             "    \"type\": \"TileMatrixSetType\","
    2079             :             "    \"title\": \"CRS84 for the World\","
    2080             :             "    \"identifier\": \"WorldCRS84Quad\","
    2081             :             "    \"boundingBox\":"
    2082             :             "    {"
    2083             :             "        \"type\": \"BoundingBoxType\","
    2084             :             "        \"crs\": "
    2085             :             "\"http://www.opengis.net/def/crs/OGC/1.X/"
    2086             :             "CRS84\","  // 1.3 modified to 1.X to test
    2087             :                         // difference with supportedCRS
    2088             :             "        \"lowerCorner\": [-180, -90],"
    2089             :             "        \"upperCorner\": [180, 90]"
    2090             :             "    },"
    2091             :             "    \"supportedCRS\": "
    2092             :             "\"http://www.opengis.net/def/crs/OGC/1.3/"
    2093             :             "CRS84\","
    2094             :             "    \"wellKnownScaleSet\": "
    2095             :             "\"http://www.opengis.net/def/wkss/OGC/1.0/"
    2096             :             "GoogleCRS84Quad\","
    2097             :             "    \"tileMatrix\":"
    2098             :             "    ["
    2099             :             "        {"
    2100             :             "            \"type\": \"TileMatrixType\","
    2101             :             "            \"identifier\": \"0\","
    2102             :             "            \"scaleDenominator\": "
    2103             :             "279541132.014358,"
    2104             :             "            \"topLeftCorner\": [-180, 90],"
    2105             :             "            \"tileWidth\": 256,"
    2106             :             "            \"tileHeight\": 256,"
    2107             :             "            \"matrixWidth\": 2,"
    2108             :             "            \"matrixHeight\": 1"
    2109             :             "        },"
    2110             :             "        {"
    2111             :             "            \"type\": \"TileMatrixType\","
    2112             :             "            \"identifier\": \"1\","
    2113             :             "            \"scaleDenominator\": 100000000,"
    2114             :             "            \"topLeftCorner\": [-123, 90],"
    2115             :             "            \"tileWidth\": 128,"
    2116             :             "            \"tileHeight\": 256,"
    2117             :             "            \"matrixWidth\": 4,"
    2118             :             "            \"matrixHeight\": 2,"
    2119             :             "            \"variableMatrixWidth\": [{"
    2120             :             "               \"type\": "
    2121             :             "\"VariableMatrixWidthType\","
    2122             :             "               \"coalesce\" : 2,"
    2123             :             "               \"minTileRow\": 0,"
    2124             :             "               \"maxTileRow\": 1"
    2125             :             "            }]"
    2126             :             "        }"
    2127             :             "    ]"
    2128           1 :             "}");
    2129           1 :         EXPECT_TRUE(poTMS != nullptr);
    2130           1 :         if (poTMS)
    2131             :         {
    2132           1 :             ASSERT_EQ(poTMS->tileMatrixList().size(), 2U);
    2133           1 :             EXPECT_TRUE(!poTMS->haveAllLevelsSameTopLeft());
    2134           1 :             EXPECT_TRUE(!poTMS->haveAllLevelsSameTileSize());
    2135           1 :             EXPECT_TRUE(!poTMS->hasOnlyPowerOfTwoVaryingScales());
    2136           1 :             EXPECT_TRUE(poTMS->hasVariableMatrixWidth());
    2137           1 :             const auto &tm = poTMS->tileMatrixList()[1];
    2138           1 :             EXPECT_EQ(tm.mVariableMatrixWidthList.size(), 1U);
    2139           1 :             const auto &vmw = tm.mVariableMatrixWidthList[0];
    2140           1 :             EXPECT_EQ(vmw.mCoalesce, 2);
    2141           1 :             EXPECT_EQ(vmw.mMinTileRow, 0);
    2142           1 :             EXPECT_EQ(vmw.mMaxTileRow, 1);
    2143             :         }
    2144             :     }
    2145             : 
    2146             :     {
    2147             :         auto poTMS = gdal::TileMatrixSet::parse(
    2148             :             "{"
    2149             :             "    \"identifier\" : \"CDBGlobalGrid\","
    2150             :             "    \"title\" : \"CDBGlobalGrid\","
    2151             :             "    \"boundingBox\" : {"
    2152             :             "        \"crs\" : \"http://www.opengis.net/def/crs/EPSG/0/4326\","
    2153             :             "        \"lowerCorner\" : ["
    2154             :             "            -90,"
    2155             :             "            -180"
    2156             :             "        ],"
    2157             :             "        \"upperCorner\" : ["
    2158             :             "            90,"
    2159             :             "            180"
    2160             :             "        ]"
    2161             :             "    },"
    2162             :             "    \"supportedCRS\" : "
    2163             :             "\"http://www.opengis.net/def/crs/EPSG/0/4326\","
    2164             :             "    \"wellKnownScaleSet\" : "
    2165             :             "\"http://www.opengis.net/def/wkss/OGC/1.0/CDBGlobalGrid\","
    2166             :             "    \"tileMatrix\" : ["
    2167             :             "        {"
    2168             :             "            \"identifier\" : \"-10\","
    2169             :             "            \"scaleDenominator\" : 397569609.975977063179,"
    2170             :             "            \"matrixWidth\" : 360,"
    2171             :             "            \"matrixHeight\" : 180,"
    2172             :             "            \"tileWidth\" : 1,"
    2173             :             "            \"tileHeight\" : 1,"
    2174             :             "            \"topLeftCorner\" : ["
    2175             :             "                90,"
    2176             :             "                -180"
    2177             :             "            ],"
    2178             :             "            \"variableMatrixWidth\" : ["
    2179             :             "                {"
    2180             :             "                \"coalesce\" : 12,"
    2181             :             "                \"minTileRow\" : 0,"
    2182             :             "                \"maxTileRow\" : 0"
    2183             :             "                },"
    2184             :             "                {"
    2185             :             "                \"coalesce\" : 12,"
    2186             :             "                \"minTileRow\" : 179,"
    2187             :             "                \"maxTileRow\" : 179"
    2188             :             "                }"
    2189             :             "            ]"
    2190             :             "        }"
    2191             :             "    ]"
    2192           1 :             "}");
    2193           1 :         EXPECT_TRUE(poTMS != nullptr);
    2194           1 :         if (poTMS)
    2195             :         {
    2196           1 :             ASSERT_EQ(poTMS->tileMatrixList().size(), 1U);
    2197           1 :             const auto &tm = poTMS->tileMatrixList()[0];
    2198           1 :             EXPECT_EQ(tm.mVariableMatrixWidthList.size(), 2U);
    2199           1 :             const auto &vmw = tm.mVariableMatrixWidthList[0];
    2200           1 :             EXPECT_EQ(vmw.mCoalesce, 12);
    2201           1 :             EXPECT_EQ(vmw.mMinTileRow, 0);
    2202           1 :             EXPECT_EQ(vmw.mMaxTileRow, 0);
    2203             :         }
    2204             :     }
    2205             : 
    2206             :     // TMS v2 (truncated version of https://maps.gnosis.earth/ogcapi/tileMatrixSets/GNOSISGlobalGrid?f=json)
    2207             :     {
    2208             :         auto poTMS = gdal::TileMatrixSet::parse(
    2209             :             "{"
    2210             :             "   \"id\" : \"GNOSISGlobalGrid\","
    2211             :             "   \"title\" : \"GNOSISGlobalGrid\","
    2212             :             "   \"uri\" : "
    2213             :             "\"http://www.opengis.net/def/tilematrixset/OGC/1.0/"
    2214             :             "GNOSISGlobalGrid\","
    2215             :             "   \"description\": \"added for testing\","
    2216             :             "   \"crs\" : \"http://www.opengis.net/def/crs/EPSG/0/4326\","
    2217             :             "   \"orderedAxes\" : ["
    2218             :             "      \"Lat\","
    2219             :             "      \"Lon\""
    2220             :             "   ],"
    2221             :             "   \"wellKnownScaleSet\" : "
    2222             :             "\"http://www.opengis.net/def/wkss/OGC/1.0/GoogleCRS84Quad\","
    2223             :             "   \"tileMatrices\" : ["
    2224             :             "      {"
    2225             :             "         \"id\" : \"0\","
    2226             :             "         \"scaleDenominator\" : 139770566.0071794390678,"
    2227             :             "         \"cellSize\" : 0.3515625,"
    2228             :             "         \"cornerOfOrigin\" : \"topLeft\","
    2229             :             "         \"pointOfOrigin\" : [ 90, -180 ],"
    2230             :             "         \"matrixWidth\" : 4,"
    2231             :             "         \"matrixHeight\" : 2,"
    2232             :             "         \"tileWidth\" : 256,"
    2233             :             "         \"tileHeight\" : 256"
    2234             :             "      },"
    2235             :             "      {"
    2236             :             "         \"id\" : \"1\","
    2237             :             "         \"scaleDenominator\" : 69885283.0035897195339,"
    2238             :             "         \"cellSize\" : 0.17578125,"
    2239             :             "         \"cornerOfOrigin\" : \"topLeft\","
    2240             :             "         \"pointOfOrigin\" : [ 90, -180 ],"
    2241             :             "         \"matrixWidth\" : 8,"
    2242             :             "         \"matrixHeight\" : 4,"
    2243             :             "         \"tileWidth\" : 256,"
    2244             :             "         \"tileHeight\" : 256,"
    2245             :             "         \"variableMatrixWidths\" : ["
    2246             :             "            { \"coalesce\" : 2, \"minTileRow\" : 0, "
    2247             :             "\"maxTileRow\" : 0 },"
    2248             :             "            { \"coalesce\" : 2, \"minTileRow\" : 3, "
    2249             :             "\"maxTileRow\" : 3 }"
    2250             :             "         ]"
    2251             :             "      }"
    2252             :             "   ]"
    2253           1 :             "}");
    2254           1 :         EXPECT_TRUE(poTMS != nullptr);
    2255           1 :         if (poTMS)
    2256             :         {
    2257           1 :             EXPECT_EQ(poTMS->title(), "GNOSISGlobalGrid");
    2258           1 :             EXPECT_EQ(poTMS->identifier(), "GNOSISGlobalGrid");
    2259           1 :             EXPECT_EQ(poTMS->abstract(), "added for testing");
    2260           1 :             EXPECT_EQ(poTMS->crs(),
    2261             :                       "http://www.opengis.net/def/crs/EPSG/0/4326");
    2262           1 :             EXPECT_EQ(
    2263             :                 poTMS->wellKnownScaleSet(),
    2264             :                 "http://www.opengis.net/def/wkss/OGC/1.0/GoogleCRS84Quad");
    2265           1 :             ASSERT_EQ(poTMS->tileMatrixList().size(), 2U);
    2266           1 :             EXPECT_TRUE(poTMS->haveAllLevelsSameTopLeft());
    2267           1 :             EXPECT_TRUE(poTMS->haveAllLevelsSameTileSize());
    2268           1 :             EXPECT_TRUE(poTMS->hasOnlyPowerOfTwoVaryingScales());
    2269             :             {
    2270           1 :                 const auto &tm = poTMS->tileMatrixList()[0];
    2271           1 :                 EXPECT_EQ(tm.mId, "0");
    2272           1 :                 EXPECT_EQ(tm.mScaleDenominator, 139770566.0071794390678);
    2273           1 :                 EXPECT_TRUE(fabs(tm.mResX - tm.mScaleDenominator * 0.28e-3 /
    2274             :                                                 (6378137. * M_PI / 180)) <
    2275             :                             1e-10);
    2276           1 :                 EXPECT_EQ(tm.mResY, tm.mResX);
    2277           1 :                 EXPECT_EQ(tm.mTopLeftX, 90.0);
    2278           1 :                 EXPECT_EQ(tm.mTopLeftY, -180.0);
    2279           1 :                 EXPECT_EQ(tm.mTileWidth, 256);
    2280           1 :                 EXPECT_EQ(tm.mTileHeight, 256);
    2281           1 :                 EXPECT_EQ(tm.mMatrixWidth, 4);
    2282           1 :                 EXPECT_EQ(tm.mMatrixHeight, 2);
    2283             :             }
    2284             : 
    2285           1 :             EXPECT_TRUE(poTMS->hasVariableMatrixWidth());
    2286             :             {
    2287           1 :                 const auto &tm = poTMS->tileMatrixList()[1];
    2288           1 :                 EXPECT_EQ(tm.mVariableMatrixWidthList.size(), 2U);
    2289           1 :                 const auto &vmw = tm.mVariableMatrixWidthList[1];
    2290           1 :                 EXPECT_EQ(vmw.mCoalesce, 2);
    2291           1 :                 EXPECT_EQ(vmw.mMinTileRow, 3);
    2292           1 :                 EXPECT_EQ(vmw.mMaxTileRow, 3);
    2293             :             }
    2294             :         }
    2295             :     }
    2296             : }
    2297             : 
    2298             : // Test that PCIDSK GetMetadataItem() return is stable
    2299           4 : TEST_F(test_gdal, PCIDSK_GetMetadataItem)
    2300             : {
    2301           1 :     auto poDrv = GDALDriver::FromHandle(GDALGetDriverByName("PCIDSK"));
    2302           1 :     if (poDrv == nullptr)
    2303           0 :         GTEST_SKIP() << "PCIDSK driver missing";
    2304             : 
    2305             :     GDALDatasetUniquePtr poDS(
    2306           2 :         poDrv->Create("/vsimem/tmp.pix", 1, 1, 1, GDT_Byte, nullptr));
    2307           1 :     EXPECT_TRUE(poDS != nullptr);
    2308           1 :     poDS->SetMetadataItem("FOO", "BAR");
    2309           1 :     poDS->SetMetadataItem("BAR", "BAZ");
    2310           1 :     poDS->GetRasterBand(1)->SetMetadataItem("FOO", "BAR");
    2311           1 :     poDS->GetRasterBand(1)->SetMetadataItem("BAR", "BAZ");
    2312             : 
    2313             :     {
    2314           1 :         const char *psz1 = poDS->GetMetadataItem("FOO");
    2315           1 :         const char *psz2 = poDS->GetMetadataItem("BAR");
    2316           1 :         const char *pszNull = poDS->GetMetadataItem("I_DONT_EXIST");
    2317           1 :         const char *psz3 = poDS->GetMetadataItem("FOO");
    2318           1 :         const char *pszNull2 = poDS->GetMetadataItem("I_DONT_EXIST");
    2319           1 :         const char *psz4 = poDS->GetMetadataItem("BAR");
    2320           1 :         EXPECT_TRUE(psz1 != nullptr);
    2321           1 :         EXPECT_TRUE(psz2 != nullptr);
    2322           1 :         EXPECT_TRUE(psz3 != nullptr);
    2323           1 :         EXPECT_TRUE(psz4 != nullptr);
    2324           1 :         EXPECT_TRUE(pszNull == nullptr);
    2325           1 :         EXPECT_TRUE(pszNull2 == nullptr);
    2326           1 :         EXPECT_EQ(psz1, psz3);
    2327           1 :         EXPECT_TRUE(psz1 != psz2);
    2328           1 :         EXPECT_EQ(psz2, psz4);
    2329           1 :         EXPECT_STREQ(psz1, "BAR");
    2330           1 :         EXPECT_STREQ(psz2, "BAZ");
    2331             :     }
    2332             : 
    2333             :     {
    2334           1 :         auto poBand = poDS->GetRasterBand(1);
    2335           1 :         const char *psz1 = poBand->GetMetadataItem("FOO");
    2336           1 :         const char *psz2 = poBand->GetMetadataItem("BAR");
    2337           1 :         const char *pszNull = poBand->GetMetadataItem("I_DONT_EXIST");
    2338           1 :         const char *psz3 = poBand->GetMetadataItem("FOO");
    2339           1 :         const char *pszNull2 = poBand->GetMetadataItem("I_DONT_EXIST");
    2340           1 :         const char *psz4 = poBand->GetMetadataItem("BAR");
    2341           1 :         EXPECT_TRUE(psz1 != nullptr);
    2342           1 :         EXPECT_TRUE(psz2 != nullptr);
    2343           1 :         EXPECT_TRUE(psz3 != nullptr);
    2344           1 :         EXPECT_TRUE(psz4 != nullptr);
    2345           1 :         EXPECT_TRUE(pszNull == nullptr);
    2346           1 :         EXPECT_TRUE(pszNull2 == nullptr);
    2347           1 :         EXPECT_EQ(psz1, psz3);
    2348           1 :         EXPECT_TRUE(psz1 != psz2);
    2349           1 :         EXPECT_EQ(psz2, psz4);
    2350           1 :         EXPECT_STREQ(psz1, "BAR");
    2351           1 :         EXPECT_STREQ(psz2, "BAZ");
    2352             :     }
    2353             : 
    2354           1 :     poDS.reset();
    2355           1 :     VSIUnlink("/vsimem/tmp.pix");
    2356             : }
    2357             : 
    2358             : // Test GDALBufferHasOnlyNoData()
    2359           4 : TEST_F(test_gdal, GDALBufferHasOnlyNoData)
    2360             : {
    2361             :     /* bool CPL_DLL GDALBufferHasOnlyNoData(const void* pBuffer,
    2362             :                                  double dfNoDataValue,
    2363             :                                  size_t nWidth, size_t nHeight,
    2364             :                                  size_t nLineStride,
    2365             :                                  size_t nComponents,
    2366             :                                  int nBitsPerSample,
    2367             :                                  GDALBufferSampleFormat nSampleFormat);
    2368             :      */
    2369           1 :     EXPECT_TRUE(
    2370             :         GDALBufferHasOnlyNoData("\x00", 0.0, 1, 1, 1, 1, 8, GSF_UNSIGNED_INT));
    2371           1 :     EXPECT_TRUE(
    2372             :         !GDALBufferHasOnlyNoData("\x01", 0.0, 1, 1, 1, 1, 8, GSF_UNSIGNED_INT));
    2373           1 :     EXPECT_TRUE(
    2374             :         GDALBufferHasOnlyNoData("\x00", 0.0, 1, 1, 1, 1, 1, GSF_UNSIGNED_INT));
    2375           1 :     EXPECT_TRUE(GDALBufferHasOnlyNoData("\x00\x00", 0.0, 1, 1, 1, 1, 16,
    2376             :                                         GSF_UNSIGNED_INT));
    2377           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData("\x00\x01", 0.0, 1, 1, 1, 1, 16,
    2378             :                                          GSF_UNSIGNED_INT));
    2379           1 :     EXPECT_TRUE(GDALBufferHasOnlyNoData("\x00\x01", 0.0, 1, 2, 2, 1, 8,
    2380             :                                         GSF_UNSIGNED_INT));
    2381           1 :     EXPECT_TRUE(GDALBufferHasOnlyNoData(
    2382             :         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 0.0, 14, 1,
    2383             :         14, 1, 8, GSF_UNSIGNED_INT));
    2384           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(
    2385             :         "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 0.0, 14, 1,
    2386             :         14, 1, 8, GSF_UNSIGNED_INT));
    2387           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(
    2388             :         "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00", 0.0, 14, 1,
    2389             :         14, 1, 8, GSF_UNSIGNED_INT));
    2390           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(
    2391             :         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 0.0, 14, 1,
    2392             :         14, 1, 8, GSF_UNSIGNED_INT));
    2393             : 
    2394           1 :     uint8_t uint8val = 1;
    2395           1 :     EXPECT_TRUE(GDALBufferHasOnlyNoData(&uint8val, 1.0, 1, 1, 1, 1, 8,
    2396             :                                         GSF_UNSIGNED_INT));
    2397           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(&uint8val, 0.0, 1, 1, 1, 1, 8,
    2398             :                                          GSF_UNSIGNED_INT));
    2399           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(&uint8val, 128 + 1, 1, 1, 1, 1, 8,
    2400             :                                          GSF_UNSIGNED_INT));
    2401             : 
    2402           1 :     int8_t int8val = -1;
    2403           1 :     EXPECT_TRUE(
    2404             :         GDALBufferHasOnlyNoData(&int8val, -1.0, 1, 1, 1, 1, 8, GSF_SIGNED_INT));
    2405           1 :     EXPECT_TRUE(
    2406             :         !GDALBufferHasOnlyNoData(&int8val, 0.0, 1, 1, 1, 1, 8, GSF_SIGNED_INT));
    2407           1 :     EXPECT_TRUE(
    2408             :         !GDALBufferHasOnlyNoData(&int8val, 256, 1, 1, 1, 1, 8, GSF_SIGNED_INT));
    2409             : 
    2410           1 :     uint16_t uint16val = 1;
    2411           1 :     EXPECT_TRUE(GDALBufferHasOnlyNoData(&uint16val, 1.0, 1, 1, 1, 1, 16,
    2412             :                                         GSF_UNSIGNED_INT));
    2413           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(&uint16val, 0.0, 1, 1, 1, 1, 16,
    2414             :                                          GSF_UNSIGNED_INT));
    2415           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(&uint16val, 65536 + 1, 1, 1, 1, 1, 16,
    2416             :                                          GSF_UNSIGNED_INT));
    2417             : 
    2418           1 :     int16_t int16val = -1;
    2419           1 :     EXPECT_TRUE(GDALBufferHasOnlyNoData(&int16val, -1.0, 1, 1, 1, 1, 16,
    2420             :                                         GSF_SIGNED_INT));
    2421           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(&int16val, 0.0, 1, 1, 1, 1, 16,
    2422             :                                          GSF_SIGNED_INT));
    2423           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(&int16val, 32768, 1, 1, 1, 1, 16,
    2424             :                                          GSF_SIGNED_INT));
    2425             : 
    2426           1 :     uint32_t uint32val = 1;
    2427           1 :     EXPECT_TRUE(GDALBufferHasOnlyNoData(&uint32val, 1.0, 1, 1, 1, 1, 32,
    2428             :                                         GSF_UNSIGNED_INT));
    2429           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(&uint32val, 0.0, 1, 1, 1, 1, 32,
    2430             :                                          GSF_UNSIGNED_INT));
    2431           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(&uint32val,
    2432             :                                          static_cast<double>(0x100000000LL + 1),
    2433             :                                          1, 1, 1, 1, 32, GSF_UNSIGNED_INT));
    2434             : 
    2435           1 :     int32_t int32val = -1;
    2436           1 :     EXPECT_TRUE(GDALBufferHasOnlyNoData(&int32val, -1.0, 1, 1, 1, 1, 32,
    2437             :                                         GSF_SIGNED_INT));
    2438           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(&int32val, 0.0, 1, 1, 1, 1, 32,
    2439             :                                          GSF_SIGNED_INT));
    2440           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(&int32val, 0x80000000, 1, 1, 1, 1, 32,
    2441             :                                          GSF_SIGNED_INT));
    2442             : 
    2443           1 :     float float32val = -1;
    2444           1 :     EXPECT_TRUE(GDALBufferHasOnlyNoData(&float32val, -1.0, 1, 1, 1, 1, 32,
    2445             :                                         GSF_FLOATING_POINT));
    2446           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(&float32val, 0.0, 1, 1, 1, 1, 32,
    2447             :                                          GSF_FLOATING_POINT));
    2448           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(&float32val, 1e50, 1, 1, 1, 1, 32,
    2449             :                                          GSF_FLOATING_POINT));
    2450             : 
    2451           1 :     float float32nan = std::numeric_limits<float>::quiet_NaN();
    2452           1 :     EXPECT_TRUE(GDALBufferHasOnlyNoData(&float32nan, float32nan, 1, 1, 1, 1, 32,
    2453             :                                         GSF_FLOATING_POINT));
    2454           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(&float32nan, 0.0, 1, 1, 1, 1, 32,
    2455             :                                          GSF_FLOATING_POINT));
    2456             : 
    2457           1 :     double float64val = -1;
    2458           1 :     EXPECT_TRUE(GDALBufferHasOnlyNoData(&float64val, -1.0, 1, 1, 1, 1, 64,
    2459             :                                         GSF_FLOATING_POINT));
    2460           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(&float64val, 0.0, 1, 1, 1, 1, 64,
    2461             :                                          GSF_FLOATING_POINT));
    2462             : 
    2463           1 :     double float64nan = std::numeric_limits<double>::quiet_NaN();
    2464           1 :     EXPECT_TRUE(GDALBufferHasOnlyNoData(&float64nan, float64nan, 1, 1, 1, 1, 64,
    2465             :                                         GSF_FLOATING_POINT));
    2466           1 :     EXPECT_TRUE(!GDALBufferHasOnlyNoData(&float64nan, 0.0, 1, 1, 1, 1, 64,
    2467             :                                          GSF_FLOATING_POINT));
    2468           1 : }
    2469             : 
    2470             : // Test GetRasterNoDataReplacementValue()
    2471           4 : TEST_F(test_gdal, GetRasterNoDataReplacementValue)
    2472             : {
    2473             :     // Test GDT_Byte
    2474           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2475             :                   GDT_Byte, std::numeric_limits<double>::lowest()),
    2476             :               0);
    2477           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(GDT_Byte,
    2478             :                                             std::numeric_limits<double>::max()),
    2479             :               0);
    2480           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2481             :                   GDT_Byte, std::numeric_limits<uint8_t>::lowest()),
    2482             :               std::numeric_limits<uint8_t>::lowest() + 1);
    2483           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2484             :                   GDT_Byte, std::numeric_limits<uint8_t>::max()),
    2485             :               std::numeric_limits<uint8_t>::max() - 1);
    2486             : 
    2487             :     // Test GDT_Int8
    2488           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2489             :                   GDT_Int8, std::numeric_limits<double>::lowest()),
    2490             :               0);
    2491           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(GDT_Int8,
    2492             :                                             std::numeric_limits<double>::max()),
    2493             :               0);
    2494           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2495             :                   GDT_Int8, std::numeric_limits<int8_t>::lowest()),
    2496             :               std::numeric_limits<int8_t>::lowest() + 1);
    2497           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(GDT_Int8,
    2498             :                                             std::numeric_limits<int8_t>::max()),
    2499             :               std::numeric_limits<int8_t>::max() - 1);
    2500             : 
    2501             :     // Test GDT_UInt16
    2502           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2503             :                   GDT_UInt16, std::numeric_limits<double>::lowest()),
    2504             :               0);
    2505           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(GDT_UInt16,
    2506             :                                             std::numeric_limits<double>::max()),
    2507             :               0);
    2508           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2509             :                   GDT_UInt16, std::numeric_limits<uint16_t>::lowest()),
    2510             :               std::numeric_limits<uint16_t>::lowest() + 1);
    2511           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2512             :                   GDT_UInt16, std::numeric_limits<uint16_t>::max()),
    2513             :               std::numeric_limits<uint16_t>::max() - 1);
    2514             : 
    2515             :     // Test GDT_Int16
    2516           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2517             :                   GDT_Int16, std::numeric_limits<double>::lowest()),
    2518             :               0);
    2519           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(GDT_Int16,
    2520             :                                             std::numeric_limits<double>::max()),
    2521             :               0);
    2522           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2523             :                   GDT_Int16, std::numeric_limits<int16_t>::lowest()),
    2524             :               std::numeric_limits<int16_t>::lowest() + 1);
    2525           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2526             :                   GDT_Int16, std::numeric_limits<int16_t>::max()),
    2527             :               std::numeric_limits<int16_t>::max() - 1);
    2528             : 
    2529             :     // Test GDT_UInt32
    2530           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2531             :                   GDT_UInt32, std::numeric_limits<double>::lowest()),
    2532             :               0);
    2533           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(GDT_UInt32,
    2534             :                                             std::numeric_limits<double>::max()),
    2535             :               0);
    2536           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2537             :                   GDT_UInt32, std::numeric_limits<uint32_t>::lowest()),
    2538             :               std::numeric_limits<uint32_t>::lowest() + 1);
    2539           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2540             :                   GDT_UInt32, std::numeric_limits<uint32_t>::max()),
    2541             :               std::numeric_limits<uint32_t>::max() - 1);
    2542             : 
    2543             :     // Test GDT_Int32
    2544           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2545             :                   GDT_Int32, std::numeric_limits<double>::lowest()),
    2546             :               0);
    2547           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(GDT_Int32,
    2548             :                                             std::numeric_limits<double>::max()),
    2549             :               0);
    2550           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2551             :                   GDT_Int32, std::numeric_limits<int32_t>::lowest()),
    2552             :               std::numeric_limits<int32_t>::lowest() + 1);
    2553           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2554             :                   GDT_Int32, std::numeric_limits<int32_t>::max()),
    2555             :               std::numeric_limits<int32_t>::max() - 1);
    2556             : 
    2557             :     // Test GDT_UInt64
    2558           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2559             :                   GDT_UInt64, std::numeric_limits<double>::lowest()),
    2560             :               0);
    2561           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(GDT_UInt64,
    2562             :                                             std::numeric_limits<double>::max()),
    2563             :               0);
    2564           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2565             :                   GDT_UInt64,
    2566             :                   static_cast<double>(std::numeric_limits<uint64_t>::lowest())),
    2567             :               static_cast<double>(std::numeric_limits<uint64_t>::lowest()) + 1);
    2568             :     // uin64_t max is not representable in double so we expect the next value to be returned
    2569           1 :     EXPECT_EQ(
    2570             :         GDALGetNoDataReplacementValue(
    2571             :             GDT_UInt64,
    2572             :             static_cast<double>(std::numeric_limits<uint64_t>::max())),
    2573             :         std::nextafter(
    2574             :             static_cast<double>(std::numeric_limits<uint64_t>::max()), 0) -
    2575             :             1);
    2576             : 
    2577             :     // Test GDT_Int64
    2578           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2579             :                   GDT_Int64, std::numeric_limits<double>::lowest()),
    2580             :               0);
    2581           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(GDT_Int64,
    2582             :                                             std::numeric_limits<double>::max()),
    2583             :               0);
    2584             :     // in64_t max is not representable in double so we expect the next value to be returned
    2585           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2586             :                   GDT_Int64,
    2587             :                   static_cast<double>(std::numeric_limits<int64_t>::lowest())),
    2588             :               static_cast<double>(std::numeric_limits<int64_t>::lowest()) + 1);
    2589           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2590             :                   GDT_Int64,
    2591             :                   static_cast<double>(std::numeric_limits<int64_t>::max())),
    2592             :               std::nextafter(
    2593             :                   static_cast<double>(std::numeric_limits<int64_t>::max()), 0) -
    2594             :                   1);
    2595             : 
    2596             :     // Test floating point types
    2597             : 
    2598             :     // out of range for float32
    2599           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2600             :                   GDT_Float32, std::numeric_limits<double>::lowest()),
    2601             :               0.0);
    2602           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(GDT_Float32,
    2603             :                                             std::numeric_limits<double>::max()),
    2604             :               0.0);
    2605           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2606             :                   GDT_Float32, std::numeric_limits<double>::infinity()),
    2607             :               0.0);
    2608           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2609             :                   GDT_Float32, -std::numeric_limits<double>::infinity()),
    2610             :               0.0);
    2611             : 
    2612             :     // in range for float 32
    2613           1 :     EXPECT_EQ(
    2614             :         static_cast<float>(GDALGetNoDataReplacementValue(GDT_Float32, -1.0)),
    2615             :         std::nextafter(float(-1.0), 0.0f));
    2616           1 :     EXPECT_EQ(
    2617             :         static_cast<float>(GDALGetNoDataReplacementValue(GDT_Float32, 1.1)),
    2618             :         std::nextafter(float(1.1), 2.0f));
    2619           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2620             :                   GDT_Float32, std::numeric_limits<float>::lowest()),
    2621             :               std::nextafter(std::numeric_limits<float>::lowest(), 0.0f));
    2622             : 
    2623           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(GDT_Float32,
    2624             :                                             std::numeric_limits<float>::max()),
    2625             :               static_cast<double>(
    2626             :                   std::nextafter(std::numeric_limits<float>::max(), 0.0f)));
    2627             : 
    2628             :     // in range for float64
    2629           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2630             :                   GDT_Float64, std::numeric_limits<double>::lowest()),
    2631             :               std::nextafter(std::numeric_limits<double>::lowest(), 0.0));
    2632           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(GDT_Float64,
    2633             :                                             std::numeric_limits<double>::max()),
    2634             :               std::nextafter(std::numeric_limits<double>::max(), 0.0));
    2635             : 
    2636           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2637             :                   GDT_Float64, std::numeric_limits<double>::lowest()),
    2638             :               std::nextafter(std::numeric_limits<double>::lowest(), 0.0));
    2639           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(GDT_Float64,
    2640             :                                             std::numeric_limits<double>::max()),
    2641             :               std::nextafter(std::numeric_limits<double>::max(), 0.0));
    2642             : 
    2643           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(GDT_Float64, double(-1.0)),
    2644             :               std::nextafter(double(-1.0), 0.0));
    2645           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(GDT_Float64, double(1.1)),
    2646             :               std::nextafter(double(1.1), 2.0));
    2647             : 
    2648             :     // test infinity
    2649           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2650             :                   GDT_Float64, std::numeric_limits<double>::infinity()),
    2651             :               0.0);
    2652           1 :     EXPECT_EQ(GDALGetNoDataReplacementValue(
    2653             :                   GDT_Float64, -std::numeric_limits<double>::infinity()),
    2654             :               0.0);
    2655           1 : }
    2656             : 
    2657             : // Test GDALRasterBand::GetIndexColorTranslationTo()
    2658           4 : TEST_F(test_gdal, GetIndexColorTranslationTo)
    2659             : {
    2660             :     GDALDatasetUniquePtr poSrcDS(
    2661             :         GDALDriver::FromHandle(GDALGetDriverByName("MEM"))
    2662           2 :             ->Create("", 1, 1, 1, GDT_Byte, nullptr));
    2663             :     {
    2664           2 :         GDALColorTable oCT;
    2665             :         {
    2666             :             GDALColorEntry e;
    2667           1 :             e.c1 = 0;
    2668           1 :             e.c2 = 0;
    2669           1 :             e.c3 = 0;
    2670           1 :             e.c4 = 255;
    2671           1 :             oCT.SetColorEntry(0, &e);
    2672             :         }
    2673             :         {
    2674             :             GDALColorEntry e;
    2675           1 :             e.c1 = 1;
    2676           1 :             e.c2 = 0;
    2677           1 :             e.c3 = 0;
    2678           1 :             e.c4 = 255;
    2679           1 :             oCT.SetColorEntry(1, &e);
    2680             :         }
    2681             :         {
    2682             :             GDALColorEntry e;
    2683           1 :             e.c1 = 255;
    2684           1 :             e.c2 = 255;
    2685           1 :             e.c3 = 255;
    2686           1 :             e.c4 = 255;
    2687           1 :             oCT.SetColorEntry(2, &e);
    2688             :         }
    2689             :         {
    2690             :             GDALColorEntry e;
    2691           1 :             e.c1 = 125;
    2692           1 :             e.c2 = 126;
    2693           1 :             e.c3 = 127;
    2694           1 :             e.c4 = 0;
    2695           1 :             oCT.SetColorEntry(3, &e);
    2696           1 :             poSrcDS->GetRasterBand(1)->SetNoDataValue(3);
    2697             :         }
    2698           1 :         poSrcDS->GetRasterBand(1)->SetColorTable(&oCT);
    2699             :     }
    2700             : 
    2701             :     GDALDatasetUniquePtr poDstDS(
    2702             :         GDALDriver::FromHandle(GDALGetDriverByName("MEM"))
    2703           2 :             ->Create("", 1, 1, 1, GDT_Byte, nullptr));
    2704             :     {
    2705           2 :         GDALColorTable oCT;
    2706             :         {
    2707             :             GDALColorEntry e;
    2708           1 :             e.c1 = 255;
    2709           1 :             e.c2 = 255;
    2710           1 :             e.c3 = 255;
    2711           1 :             e.c4 = 255;
    2712           1 :             oCT.SetColorEntry(0, &e);
    2713             :         }
    2714             :         {
    2715             :             GDALColorEntry e;
    2716           1 :             e.c1 = 0;
    2717           1 :             e.c2 = 0;
    2718           1 :             e.c3 = 1;
    2719           1 :             e.c4 = 255;
    2720           1 :             oCT.SetColorEntry(1, &e);
    2721             :         }
    2722             :         {
    2723             :             GDALColorEntry e;
    2724           1 :             e.c1 = 12;
    2725           1 :             e.c2 = 13;
    2726           1 :             e.c3 = 14;
    2727           1 :             e.c4 = 0;
    2728           1 :             oCT.SetColorEntry(2, &e);
    2729           1 :             poSrcDS->GetRasterBand(1)->SetNoDataValue(2);
    2730             :         }
    2731           1 :         poDstDS->GetRasterBand(1)->SetColorTable(&oCT);
    2732             :     }
    2733             : 
    2734             :     unsigned char *panTranslationTable =
    2735           1 :         poSrcDS->GetRasterBand(1)->GetIndexColorTranslationTo(
    2736             :             poDstDS->GetRasterBand(1));
    2737           1 :     EXPECT_EQ(static_cast<int>(panTranslationTable[0]), 1);
    2738           1 :     EXPECT_EQ(static_cast<int>(panTranslationTable[1]), 1);
    2739           1 :     EXPECT_EQ(static_cast<int>(panTranslationTable[2]), 0);
    2740           1 :     EXPECT_EQ(static_cast<int>(panTranslationTable[3]),
    2741             :               2);  // special nodata mapping
    2742           1 :     CPLFree(panTranslationTable);
    2743           1 : }
    2744             : 
    2745             : // Test effect of MarkSuppressOnClose() with the final FlushCache() at dataset
    2746             : // destruction
    2747           4 : TEST_F(test_gdal, MarkSuppressOnClose)
    2748             : {
    2749           1 :     const char *pszFilename = "/vsimem/out.tif";
    2750           1 :     const char *const apszOptions[] = {"PROFILE=BASELINE", nullptr};
    2751             :     {
    2752             :         GDALDatasetUniquePtr poDstDS(
    2753             :             GDALDriver::FromHandle(GDALGetDriverByName("GTiff"))
    2754           2 :                 ->Create(pszFilename, 1, 1, 1, GDT_Byte, apszOptions));
    2755           1 :         poDstDS->SetMetadataItem("FOO", "BAR");
    2756           1 :         poDstDS->MarkSuppressOnClose();
    2757           1 :         poDstDS->GetRasterBand(1)->Fill(255);
    2758           1 :         poDstDS->FlushCache(true);
    2759             :         // All buffers have been flushed, but our dirty block should not have
    2760             :         // been written hence the checksum will be 0
    2761           1 :         EXPECT_EQ(GDALChecksumImage(
    2762             :                       GDALRasterBand::FromHandle(poDstDS->GetRasterBand(1)), 0,
    2763             :                       0, 1, 1),
    2764             :                   0);
    2765             :     }
    2766             :     {
    2767             :         VSIStatBufL sStat;
    2768           1 :         EXPECT_TRUE(VSIStatL(CPLSPrintf("%s.aux.xml", pszFilename), &sStat) !=
    2769             :                     0);
    2770             :     }
    2771           1 : }
    2772             : 
    2773             : // Test effect of UnMarkSuppressOnClose()
    2774           4 : TEST_F(test_gdal, UnMarkSuppressOnClose)
    2775             : {
    2776           1 :     const char *pszFilename = "/vsimem/out.tif";
    2777           1 :     const char *const apszOptions[] = {"PROFILE=BASELINE", nullptr};
    2778             :     {
    2779             :         GDALDatasetUniquePtr poDstDS(
    2780             :             GDALDriver::FromHandle(GDALGetDriverByName("GTiff"))
    2781           2 :                 ->Create(pszFilename, 1, 1, 1, GDT_Byte, apszOptions));
    2782           1 :         poDstDS->MarkSuppressOnClose();
    2783           1 :         poDstDS->GetRasterBand(1)->Fill(255);
    2784           1 :         if (poDstDS->IsMarkedSuppressOnClose())
    2785           1 :             poDstDS->UnMarkSuppressOnClose();
    2786           1 :         poDstDS->FlushCache(true);
    2787             :         // All buffers have been flushed, and our dirty block should have
    2788             :         // been written hence the checksum will not be 0
    2789           1 :         EXPECT_NE(GDALChecksumImage(
    2790             :                       GDALRasterBand::FromHandle(poDstDS->GetRasterBand(1)), 0,
    2791             :                       0, 1, 1),
    2792             :                   0);
    2793             :         VSIStatBufL sStat;
    2794           1 :         EXPECT_TRUE(VSIStatL(pszFilename, &sStat) == 0);
    2795           1 :         VSIUnlink(pszFilename);
    2796             :     }
    2797           1 : }
    2798             : 
    2799          11 : template <class T> void TestCachedPixelAccessor()
    2800             : {
    2801          11 :     constexpr auto eType = GDALCachedPixelAccessorGetDataType<T>::DataType;
    2802          22 :     auto poDS = std::unique_ptr<GDALDataset>(
    2803             :         GDALDriver::FromHandle(GDALGetDriverByName("MEM"))
    2804             :             ->Create("", 11, 23, 1, eType, nullptr));
    2805          11 :     auto poBand = poDS->GetRasterBand(1);
    2806          22 :     GDALCachedPixelAccessor<T, 4> accessor(poBand);
    2807         264 :     for (int iY = 0; iY < poBand->GetYSize(); iY++)
    2808             :     {
    2809        3036 :         for (int iX = 0; iX < poBand->GetXSize(); iX++)
    2810             :         {
    2811        2783 :             accessor.Set(iX, iY, static_cast<T>(iY * poBand->GetXSize() + iX));
    2812             :         }
    2813             :     }
    2814         264 :     for (int iY = 0; iY < poBand->GetYSize(); iY++)
    2815             :     {
    2816        3036 :         for (int iX = 0; iX < poBand->GetXSize(); iX++)
    2817             :         {
    2818        2783 :             EXPECT_EQ(accessor.Get(iX, iY),
    2819             :                       static_cast<T>(iY * poBand->GetXSize() + iX));
    2820             :         }
    2821             :     }
    2822             : 
    2823          22 :     std::vector<T> values(static_cast<size_t>(poBand->GetYSize()) *
    2824          11 :                           poBand->GetXSize());
    2825          11 :     accessor.FlushCache();
    2826          11 :     EXPECT_EQ(poBand->RasterIO(GF_Read, 0, 0, poBand->GetXSize(),
    2827             :                                poBand->GetYSize(), values.data(),
    2828             :                                poBand->GetXSize(), poBand->GetYSize(), eType, 0,
    2829             :                                0, nullptr),
    2830             :               CE_None);
    2831         264 :     for (int iY = 0; iY < poBand->GetYSize(); iY++)
    2832             :     {
    2833        3036 :         for (int iX = 0; iX < poBand->GetXSize(); iX++)
    2834             :         {
    2835        2783 :             EXPECT_EQ(values[iY * poBand->GetXSize() + iX],
    2836             :                       static_cast<T>(iY * poBand->GetXSize() + iX));
    2837             :         }
    2838             :     }
    2839          11 : }
    2840             : 
    2841             : // Test GDALCachedPixelAccessor
    2842           4 : TEST_F(test_gdal, GDALCachedPixelAccessor)
    2843             : {
    2844           1 :     TestCachedPixelAccessor<GByte>();
    2845           1 :     TestCachedPixelAccessor<GUInt16>();
    2846           1 :     TestCachedPixelAccessor<GInt16>();
    2847           1 :     TestCachedPixelAccessor<GUInt32>();
    2848           1 :     TestCachedPixelAccessor<GInt32>();
    2849           1 :     TestCachedPixelAccessor<GUInt64>();
    2850           1 :     TestCachedPixelAccessor<GInt64>();
    2851           1 :     TestCachedPixelAccessor<uint64_t>();
    2852           1 :     TestCachedPixelAccessor<int64_t>();
    2853           1 :     TestCachedPixelAccessor<float>();
    2854           1 :     TestCachedPixelAccessor<double>();
    2855           1 : }
    2856             : 
    2857             : // Test VRT and caching of sources w.r.t open options
    2858             : // (https://github.com/OSGeo/gdal/issues/5989)
    2859           4 : TEST_F(test_gdal, VRTCachingOpenOptions)
    2860             : {
    2861             :     class TestRasterBand : public GDALRasterBand
    2862             :     {
    2863             :       protected:
    2864           3 :         CPLErr IReadBlock(int, int, void *pImage) override
    2865             :         {
    2866           3 :             static_cast<GByte *>(pImage)[0] = 0;
    2867           3 :             return CE_None;
    2868             :         }
    2869             : 
    2870             :       public:
    2871           3 :         TestRasterBand()
    2872           3 :         {
    2873           3 :             nBlockXSize = 1;
    2874           3 :             nBlockYSize = 1;
    2875           3 :             eDataType = GDT_Byte;
    2876           3 :         }
    2877             :     };
    2878             : 
    2879             :     static int nCountZeroOpenOptions = 0;
    2880             :     static int nCountWithOneOpenOptions = 0;
    2881             : 
    2882             :     class TestDataset : public GDALDataset
    2883             :     {
    2884             :       public:
    2885           3 :         TestDataset()
    2886           3 :         {
    2887           3 :             nRasterXSize = 1;
    2888           3 :             nRasterYSize = 1;
    2889           3 :             SetBand(1, new TestRasterBand());
    2890           3 :         }
    2891             : 
    2892           3 :         static GDALDataset *TestOpen(GDALOpenInfo *poOpenInfo)
    2893             :         {
    2894           3 :             if (strcmp(poOpenInfo->pszFilename, ":::DUMMY:::") != 0)
    2895           0 :                 return nullptr;
    2896           3 :             if (poOpenInfo->papszOpenOptions == nullptr)
    2897           1 :                 nCountZeroOpenOptions++;
    2898             :             else
    2899           2 :                 nCountWithOneOpenOptions++;
    2900           3 :             return new TestDataset();
    2901             :         }
    2902             :     };
    2903             : 
    2904           2 :     std::unique_ptr<GDALDriver> driver(new GDALDriver());
    2905           1 :     driver->SetDescription("TEST_VRT_SOURCE_OPEN_OPTION");
    2906           1 :     driver->pfnOpen = TestDataset::TestOpen;
    2907           1 :     GetGDALDriverManager()->RegisterDriver(driver.get());
    2908             : 
    2909           1 :     const char *pszVRT = R"(
    2910             : <VRTDataset rasterXSize="1" rasterYSize="1">
    2911             :   <VRTRasterBand dataType="Byte" band="1" subClass="VRTSourcedRasterBand">
    2912             :     <SimpleSource>
    2913             :       <SourceFilename relativeToVRT="0">:::DUMMY:::</SourceFilename>
    2914             :     </SimpleSource>
    2915             :     <SimpleSource>
    2916             :       <SourceFilename relativeToVRT="0">:::DUMMY:::</SourceFilename>
    2917             :     </SimpleSource>
    2918             :     <SimpleSource>
    2919             :       <SourceFilename relativeToVRT="0">:::DUMMY:::</SourceFilename>
    2920             :       <OpenOptions>
    2921             :           <OOI key="TESTARG">present</OOI>
    2922             :       </OpenOptions>
    2923             :     </SimpleSource>
    2924             :     <SimpleSource>
    2925             :       <SourceFilename relativeToVRT="0">:::DUMMY:::</SourceFilename>
    2926             :       <OpenOptions>
    2927             :           <OOI key="TESTARG">present</OOI>
    2928             :       </OpenOptions>
    2929             :     </SimpleSource>
    2930             :     <SimpleSource>
    2931             :       <SourceFilename relativeToVRT="0">:::DUMMY:::</SourceFilename>
    2932             :       <OpenOptions>
    2933             :           <OOI key="TESTARG">another_one</OOI>
    2934             :       </OpenOptions>
    2935             :     </SimpleSource>
    2936             :   </VRTRasterBand>
    2937             : </VRTDataset>)";
    2938           2 :     auto ds = std::unique_ptr<GDALDataset>(GDALDataset::Open(pszVRT));
    2939             : 
    2940             :     // Trigger reading data, which triggers opening of source datasets
    2941           1 :     auto rb = ds->GetRasterBand(1);
    2942             :     double minmax[2];
    2943           1 :     GDALComputeRasterMinMax(GDALRasterBand::ToHandle(rb), TRUE, minmax);
    2944             : 
    2945           1 :     ds.reset();
    2946           1 :     GetGDALDriverManager()->DeregisterDriver(driver.get());
    2947             : 
    2948           1 :     EXPECT_EQ(nCountZeroOpenOptions, 1);
    2949           1 :     EXPECT_EQ(nCountWithOneOpenOptions, 2);
    2950           1 : }
    2951             : 
    2952             : // Test GDALDeinterleave 3 components Byte()
    2953           4 : TEST_F(test_gdal, GDALDeinterleave3ComponentsByte)
    2954             : {
    2955           1 :     GByte *pabySrc = static_cast<GByte *>(CPLMalloc(3 * 4 * 15));
    2956         181 :     for (int i = 0; i < 3 * 4 * 15; i++)
    2957         180 :         pabySrc[i] = static_cast<GByte>(i);
    2958           1 :     GByte *pabyDest0 = static_cast<GByte *>(CPLMalloc(4 * 15));
    2959           1 :     GByte *pabyDest1 = static_cast<GByte *>(CPLMalloc(4 * 15));
    2960           1 :     GByte *pabyDest2 = static_cast<GByte *>(CPLMalloc(4 * 15));
    2961           1 :     void *ppabyDest[] = {pabyDest0, pabyDest1, pabyDest2};
    2962           3 :     for (int nIters : {1, 4 * 15})
    2963             :     {
    2964           2 :         GDALDeinterleave(pabySrc, GDT_Byte, 3, ppabyDest, GDT_Byte, nIters);
    2965          63 :         for (int i = 0; i < nIters; i++)
    2966             :         {
    2967          61 :             EXPECT_EQ(pabyDest0[i], 3 * i);
    2968          61 :             EXPECT_EQ(pabyDest1[i], 3 * i + 1);
    2969          61 :             EXPECT_EQ(pabyDest2[i], 3 * i + 2);
    2970             :         }
    2971             :     }
    2972           1 :     VSIFree(pabySrc);
    2973           1 :     VSIFree(pabyDest0);
    2974           1 :     VSIFree(pabyDest1);
    2975           1 :     VSIFree(pabyDest2);
    2976           1 : }
    2977             : 
    2978             : // Test GDALDeinterleave 3 components Byte() without SSSE3
    2979           4 : TEST_F(test_gdal, GDALDeinterleave3ComponentsByte_NOSSE3)
    2980             : {
    2981           1 :     GByte *pabySrc = static_cast<GByte *>(CPLMalloc(3 * 4 * 15));
    2982         181 :     for (int i = 0; i < 3 * 4 * 15; i++)
    2983         180 :         pabySrc[i] = static_cast<GByte>(i);
    2984           1 :     GByte *pabyDest0 = static_cast<GByte *>(CPLMalloc(4 * 15));
    2985           1 :     GByte *pabyDest1 = static_cast<GByte *>(CPLMalloc(4 * 15));
    2986           1 :     GByte *pabyDest2 = static_cast<GByte *>(CPLMalloc(4 * 15));
    2987           1 :     void *ppabyDest[] = {pabyDest0, pabyDest1, pabyDest2};
    2988           3 :     for (int nIters : {1, 4 * 15})
    2989             :     {
    2990           2 :         CPLSetConfigOption("GDAL_USE_SSSE3", "NO");
    2991           2 :         GDALDeinterleave(pabySrc, GDT_Byte, 3, ppabyDest, GDT_Byte, nIters);
    2992           2 :         CPLSetConfigOption("GDAL_USE_SSSE3", nullptr);
    2993          63 :         for (int i = 0; i < nIters; i++)
    2994             :         {
    2995          61 :             EXPECT_EQ(pabyDest0[i], 3 * i);
    2996          61 :             EXPECT_EQ(pabyDest1[i], 3 * i + 1);
    2997          61 :             EXPECT_EQ(pabyDest2[i], 3 * i + 2);
    2998             :         }
    2999             :     }
    3000           1 :     VSIFree(pabySrc);
    3001           1 :     VSIFree(pabyDest0);
    3002           1 :     VSIFree(pabyDest1);
    3003           1 :     VSIFree(pabyDest2);
    3004           1 : }
    3005             : 
    3006             : // Test GDALDeinterleave 4 components Byte()
    3007           4 : TEST_F(test_gdal, GDALDeinterleave4ComponentsByte)
    3008             : {
    3009           1 :     GByte *pabySrc = static_cast<GByte *>(CPLMalloc(3 * 4 * 15));
    3010         181 :     for (int i = 0; i < 3 * 4 * 15; i++)
    3011         180 :         pabySrc[i] = static_cast<GByte>(i);
    3012           1 :     GByte *pabyDest0 = static_cast<GByte *>(CPLMalloc(3 * 15));
    3013           1 :     GByte *pabyDest1 = static_cast<GByte *>(CPLMalloc(3 * 15));
    3014           1 :     GByte *pabyDest2 = static_cast<GByte *>(CPLMalloc(3 * 15));
    3015           1 :     GByte *pabyDest3 = static_cast<GByte *>(CPLMalloc(3 * 15));
    3016           1 :     void *ppabyDest[] = {pabyDest0, pabyDest1, pabyDest2, pabyDest3};
    3017           3 :     for (int nIters : {1, 3 * 15})
    3018             :     {
    3019           2 :         GDALDeinterleave(pabySrc, GDT_Byte, 4, ppabyDest, GDT_Byte, nIters);
    3020          48 :         for (int i = 0; i < nIters; i++)
    3021             :         {
    3022          46 :             EXPECT_EQ(pabyDest0[i], 4 * i);
    3023          46 :             EXPECT_EQ(pabyDest1[i], 4 * i + 1);
    3024          46 :             EXPECT_EQ(pabyDest2[i], 4 * i + 2);
    3025          46 :             EXPECT_EQ(pabyDest3[i], 4 * i + 3);
    3026             :         }
    3027             :     }
    3028           1 :     VSIFree(pabySrc);
    3029           1 :     VSIFree(pabyDest0);
    3030           1 :     VSIFree(pabyDest1);
    3031           1 :     VSIFree(pabyDest2);
    3032           1 :     VSIFree(pabyDest3);
    3033           1 : }
    3034             : 
    3035             : // Test GDALDeinterleave 4 components Byte without SSSE3
    3036           4 : TEST_F(test_gdal, GDALDeinterleave4ComponentsByte_NOSSE3)
    3037             : {
    3038           1 :     GByte *pabySrc = static_cast<GByte *>(CPLMalloc(3 * 4 * 15));
    3039         181 :     for (int i = 0; i < 3 * 4 * 15; i++)
    3040         180 :         pabySrc[i] = static_cast<GByte>(i);
    3041           1 :     GByte *pabyDest0 = static_cast<GByte *>(CPLMalloc(3 * 15));
    3042           1 :     GByte *pabyDest1 = static_cast<GByte *>(CPLMalloc(3 * 15));
    3043           1 :     GByte *pabyDest2 = static_cast<GByte *>(CPLMalloc(3 * 15));
    3044           1 :     GByte *pabyDest3 = static_cast<GByte *>(CPLMalloc(3 * 15));
    3045           1 :     void *ppabyDest[] = {pabyDest0, pabyDest1, pabyDest2, pabyDest3};
    3046           3 :     for (int nIters : {1, 3 * 15})
    3047             :     {
    3048           2 :         CPLSetConfigOption("GDAL_USE_SSSE3", "NO");
    3049           2 :         GDALDeinterleave(pabySrc, GDT_Byte, 4, ppabyDest, GDT_Byte, nIters);
    3050           2 :         CPLSetConfigOption("GDAL_USE_SSSE3", nullptr);
    3051          48 :         for (int i = 0; i < nIters; i++)
    3052             :         {
    3053          46 :             EXPECT_EQ(pabyDest0[i], 4 * i);
    3054          46 :             EXPECT_EQ(pabyDest1[i], 4 * i + 1);
    3055          46 :             EXPECT_EQ(pabyDest2[i], 4 * i + 2);
    3056          46 :             EXPECT_EQ(pabyDest3[i], 4 * i + 3);
    3057             :         }
    3058             :     }
    3059           1 :     VSIFree(pabySrc);
    3060           1 :     VSIFree(pabyDest0);
    3061           1 :     VSIFree(pabyDest1);
    3062           1 :     VSIFree(pabyDest2);
    3063           1 :     VSIFree(pabyDest3);
    3064           1 : }
    3065             : 
    3066             : // Test GDALDeinterleave general case
    3067           4 : TEST_F(test_gdal, GDALDeinterleaveGeneralCase)
    3068             : {
    3069           1 :     GByte *pabySrc = static_cast<GByte *>(CPLMalloc(3 * 2));
    3070           7 :     for (int i = 0; i < 3 * 2; i++)
    3071           6 :         pabySrc[i] = static_cast<GByte>(i);
    3072           1 :     GUInt16 *panDest0 = static_cast<GUInt16 *>(CPLMalloc(3 * sizeof(uint16_t)));
    3073           1 :     GUInt16 *panDest1 = static_cast<GUInt16 *>(CPLMalloc(3 * sizeof(uint16_t)));
    3074           1 :     void *ppanDest[] = {panDest0, panDest1};
    3075           1 :     GDALDeinterleave(pabySrc, GDT_Byte, 2, ppanDest, GDT_UInt16, 3);
    3076           4 :     for (int i = 0; i < 3; i++)
    3077             :     {
    3078           3 :         EXPECT_EQ(panDest0[i], 2 * i);
    3079           3 :         EXPECT_EQ(panDest1[i], 2 * i + 1);
    3080             :     }
    3081           1 :     VSIFree(pabySrc);
    3082           1 :     VSIFree(panDest0);
    3083           1 :     VSIFree(panDest1);
    3084           1 : }
    3085             : 
    3086             : // Test GDALDeinterleave 3 components UInt16()
    3087           4 : TEST_F(test_gdal, GDALDeinterleave3ComponentsUInt16)
    3088             : {
    3089             :     GUInt16 *panSrc =
    3090           1 :         static_cast<GUInt16 *>(CPLMalloc(3 * 4 * 15 * sizeof(GUInt16)));
    3091         181 :     for (int i = 0; i < 3 * 4 * 15; i++)
    3092         180 :         panSrc[i] = static_cast<GUInt16>(i + 32767);
    3093             :     GUInt16 *panDest0 =
    3094           1 :         static_cast<GUInt16 *>(CPLMalloc(4 * 15 * sizeof(GUInt16)));
    3095             :     GUInt16 *panDest1 =
    3096           1 :         static_cast<GUInt16 *>(CPLMalloc(4 * 15 * sizeof(GUInt16)));
    3097             :     GUInt16 *panDest2 =
    3098           1 :         static_cast<GUInt16 *>(CPLMalloc(4 * 15 * sizeof(GUInt16)));
    3099           1 :     void *ppanDest[] = {panDest0, panDest1, panDest2};
    3100           3 :     for (int nIters : {1, 4 * 15})
    3101             :     {
    3102           2 :         GDALDeinterleave(panSrc, GDT_UInt16, 3, ppanDest, GDT_UInt16, nIters);
    3103          63 :         for (int i = 0; i < nIters; i++)
    3104             :         {
    3105          61 :             EXPECT_EQ(panDest0[i], 3 * i + 32767);
    3106          61 :             EXPECT_EQ(panDest1[i], 3 * i + 1 + 32767);
    3107          61 :             EXPECT_EQ(panDest2[i], 3 * i + 2 + 32767);
    3108             :         }
    3109             :     }
    3110           1 :     VSIFree(panSrc);
    3111           1 :     VSIFree(panDest0);
    3112           1 :     VSIFree(panDest1);
    3113           1 :     VSIFree(panDest2);
    3114           1 : }
    3115             : 
    3116             : // Test GDALDeinterleave 4 components UInt16()
    3117           4 : TEST_F(test_gdal, GDALDeinterleave4ComponentsUInt16)
    3118             : {
    3119             :     GUInt16 *panSrc =
    3120           1 :         static_cast<GUInt16 *>(CPLMalloc(3 * 4 * 15 * sizeof(GUInt16)));
    3121         181 :     for (int i = 0; i < 3 * 4 * 15; i++)
    3122         180 :         panSrc[i] = static_cast<GUInt16>(i + 32767);
    3123             :     GUInt16 *panDest0 =
    3124           1 :         static_cast<GUInt16 *>(CPLMalloc(4 * 15 * sizeof(GUInt16)));
    3125             :     GUInt16 *panDest1 =
    3126           1 :         static_cast<GUInt16 *>(CPLMalloc(4 * 15 * sizeof(GUInt16)));
    3127             :     GUInt16 *panDest2 =
    3128           1 :         static_cast<GUInt16 *>(CPLMalloc(4 * 15 * sizeof(GUInt16)));
    3129             :     GUInt16 *panDest3 =
    3130           1 :         static_cast<GUInt16 *>(CPLMalloc(4 * 15 * sizeof(GUInt16)));
    3131           1 :     void *ppanDest[] = {panDest0, panDest1, panDest2, panDest3};
    3132           3 :     for (int nIters : {1, 3 * 15})
    3133             :     {
    3134           2 :         GDALDeinterleave(panSrc, GDT_UInt16, 4, ppanDest, GDT_UInt16, nIters);
    3135          48 :         for (int i = 0; i < nIters; i++)
    3136             :         {
    3137          46 :             EXPECT_EQ(panDest0[i], 4 * i + 32767);
    3138          46 :             EXPECT_EQ(panDest1[i], 4 * i + 1 + 32767);
    3139          46 :             EXPECT_EQ(panDest2[i], 4 * i + 2 + 32767);
    3140          46 :             EXPECT_EQ(panDest3[i], 4 * i + 3 + 32767);
    3141             :         }
    3142             :     }
    3143           1 :     VSIFree(panSrc);
    3144           1 :     VSIFree(panDest0);
    3145           1 :     VSIFree(panDest1);
    3146           1 :     VSIFree(panDest2);
    3147           1 :     VSIFree(panDest3);
    3148           1 : }
    3149             : 
    3150             : // Test GDALDataset::ReportError()
    3151           4 : TEST_F(test_gdal, GDALDatasetReportError)
    3152             : {
    3153             :     GDALDatasetUniquePtr poSrcDS(
    3154             :         GDALDriver::FromHandle(GDALGetDriverByName("MEM"))
    3155           2 :             ->Create("", 1, 1, 1, GDT_Byte, nullptr));
    3156             : 
    3157           1 :     CPLPushErrorHandler(CPLQuietErrorHandler);
    3158           1 :     poSrcDS->ReportError("foo", CE_Warning, CPLE_AppDefined, "bar");
    3159           1 :     CPLPopErrorHandler();
    3160           1 :     EXPECT_STREQ(CPLGetLastErrorMsg(), "foo: bar");
    3161             : 
    3162           1 :     CPLPushErrorHandler(CPLQuietErrorHandler);
    3163           1 :     poSrcDS->ReportError("%foo", CE_Warning, CPLE_AppDefined, "bar");
    3164           1 :     CPLPopErrorHandler();
    3165           1 :     EXPECT_STREQ(CPLGetLastErrorMsg(), "%foo: bar");
    3166             : 
    3167           1 :     CPLPushErrorHandler(CPLQuietErrorHandler);
    3168           1 :     poSrcDS->ReportError(
    3169             :         "this_is_"
    3170             :         "wayyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
    3171             :         "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
    3172             :         "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
    3173             :         "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
    3174             :         "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
    3175             :         "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
    3176             :         "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
    3177             :         "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
    3178             :         "yyyyyyy_too_long/foo",
    3179           1 :         CE_Warning, CPLE_AppDefined, "bar");
    3180           1 :     CPLPopErrorHandler();
    3181           1 :     EXPECT_STREQ(CPLGetLastErrorMsg(), "foo: bar");
    3182           1 : }
    3183             : 
    3184             : // Test GDALDataset::GetCompressionFormats() and ReadCompressedData()
    3185           4 : TEST_F(test_gdal, gtiff_ReadCompressedData)
    3186             : {
    3187           1 :     if (GDALGetDriverByName("JPEG") == nullptr)
    3188             :     {
    3189           0 :         GTEST_SKIP() << "JPEG support missing";
    3190             :     }
    3191             : 
    3192             :     GDALDatasetUniquePtr poSrcDS(GDALDataset::FromHandle(
    3193           1 :         GDALDataset::Open((tut::common::data_basedir +
    3194             :                            "/../../gcore/data/byte_jpg_unusual_jpegtable.tif")
    3195           1 :                               .c_str())));
    3196           1 :     ASSERT_TRUE(poSrcDS);
    3197             : 
    3198             :     const CPLStringList aosRet(GDALDatasetGetCompressionFormats(
    3199           1 :         GDALDataset::ToHandle(poSrcDS.get()), 0, 0, 20, 20, 1, nullptr));
    3200           1 :     EXPECT_EQ(aosRet.size(), 1);
    3201           1 :     if (aosRet.size() == 1)
    3202             :     {
    3203           1 :         EXPECT_STREQ(aosRet[0], "JPEG");
    3204             :     }
    3205             : 
    3206             :     {
    3207           1 :         int nBand = 1;
    3208           1 :         EXPECT_EQ(CPLStringList(GDALDatasetGetCompressionFormats(
    3209             :                                     GDALDataset::ToHandle(poSrcDS.get()), 0, 0,
    3210             :                                     20, 20, 1, &nBand))
    3211             :                       .size(),
    3212             :                   1);
    3213             :     }
    3214             : 
    3215             :     // nBandCout > nBands
    3216           1 :     EXPECT_EQ(CPLStringList(GDALDatasetGetCompressionFormats(
    3217             :                                 GDALDataset::ToHandle(poSrcDS.get()), 0, 0, 20,
    3218             :                                 20, 2, nullptr))
    3219             :                   .size(),
    3220             :               0);
    3221             : 
    3222             :     // Cannot subset just one pixel
    3223           1 :     EXPECT_EQ(CPLStringList(GDALDatasetGetCompressionFormats(
    3224             :                                 GDALDataset::ToHandle(poSrcDS.get()), 0, 0, 1,
    3225             :                                 1, 1, nullptr))
    3226             :                   .size(),
    3227             :               0);
    3228             : 
    3229             :     // Wrong band number
    3230             :     {
    3231           1 :         int nBand = 2;
    3232           1 :         EXPECT_EQ(CPLStringList(GDALDatasetGetCompressionFormats(
    3233             :                                     GDALDataset::ToHandle(poSrcDS.get()), 0, 0,
    3234             :                                     20, 20, 1, &nBand))
    3235             :                       .size(),
    3236             :                   0);
    3237             :     }
    3238             : 
    3239           1 :     EXPECT_EQ(GDALDatasetReadCompressedData(
    3240             :                   GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 20, 20, 1,
    3241             :                   nullptr, nullptr, nullptr, nullptr),
    3242             :               CE_None);
    3243             : 
    3244             :     size_t nNeededSize;
    3245             :     {
    3246           1 :         char *pszDetailedFormat = nullptr;
    3247           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3248             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 20,
    3249             :                       20, 1, nullptr, nullptr, &nNeededSize,
    3250             :                       &pszDetailedFormat),
    3251             :                   CE_None);
    3252           1 :         EXPECT_EQ(nNeededSize, 476);
    3253           1 :         EXPECT_TRUE(pszDetailedFormat != nullptr);
    3254           1 :         if (pszDetailedFormat)
    3255             :         {
    3256           1 :             ASSERT_STREQ(pszDetailedFormat, "JPEG");
    3257           1 :             VSIFree(pszDetailedFormat);
    3258             :         }
    3259             :     }
    3260             : 
    3261             :     {
    3262           1 :         const GByte abyCanary[] = {0xDE, 0xAD, 0xBE, 0xEF};
    3263           1 :         std::vector<GByte> abyBuffer(nNeededSize + sizeof(abyCanary));
    3264           1 :         memcpy(&abyBuffer[nNeededSize], abyCanary, sizeof(abyCanary));
    3265           1 :         void *pabyBuffer = abyBuffer.data();
    3266           1 :         void **ppabyBuffer = &pabyBuffer;
    3267           1 :         size_t nProvidedSize = nNeededSize;
    3268           1 :         char *pszDetailedFormat = nullptr;
    3269           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3270             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 20,
    3271             :                       20, 1, nullptr, ppabyBuffer, &nProvidedSize,
    3272             :                       &pszDetailedFormat),
    3273             :                   CE_None);
    3274           1 :         ASSERT_EQ(nProvidedSize, nNeededSize);
    3275           1 :         ASSERT_TRUE(*ppabyBuffer == pabyBuffer);
    3276           1 :         EXPECT_TRUE(pszDetailedFormat != nullptr);
    3277           1 :         if (pszDetailedFormat)
    3278             :         {
    3279           1 :             ASSERT_STREQ(pszDetailedFormat,
    3280             :                          "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_"
    3281             :                          "components=1;colorspace=unknown");
    3282           1 :             VSIFree(pszDetailedFormat);
    3283             :         }
    3284           1 :         EXPECT_TRUE(
    3285             :             memcmp(&abyBuffer[nNeededSize], abyCanary, sizeof(abyCanary)) == 0);
    3286           1 :         EXPECT_EQ(abyBuffer[0], 0xFF);
    3287           1 :         EXPECT_EQ(abyBuffer[1], 0xD8);
    3288           1 :         EXPECT_EQ(abyBuffer[nNeededSize - 2], 0xFF);
    3289           1 :         EXPECT_EQ(abyBuffer[nNeededSize - 1], 0xD9);
    3290             : 
    3291             :         // Buffer larger than needed: OK
    3292           1 :         nProvidedSize = nNeededSize + 1;
    3293           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3294             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 20,
    3295             :                       20, 1, nullptr, ppabyBuffer, &nProvidedSize, nullptr),
    3296             :                   CE_None);
    3297             : 
    3298             :         // Too small buffer
    3299           1 :         nProvidedSize = nNeededSize - 1;
    3300           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3301             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 20,
    3302             :                       20, 1, nullptr, ppabyBuffer, &nProvidedSize, nullptr),
    3303             :                   CE_Failure);
    3304             : 
    3305             :         // Missing pointer to size
    3306           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3307             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 20,
    3308             :                       20, 1, nullptr, ppabyBuffer, nullptr, nullptr),
    3309             :                   CE_Failure);
    3310             :     }
    3311             : 
    3312             :     // Let GDAL allocate buffer
    3313             :     {
    3314           1 :         void *pBuffer = nullptr;
    3315           1 :         size_t nGotSize = 0;
    3316           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3317             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 20,
    3318             :                       20, 1, nullptr, &pBuffer, &nGotSize, nullptr),
    3319             :                   CE_None);
    3320           1 :         EXPECT_EQ(nGotSize, nNeededSize);
    3321           1 :         EXPECT_NE(pBuffer, nullptr);
    3322           1 :         if (pBuffer != nullptr && nGotSize == nNeededSize)
    3323             :         {
    3324           1 :             const GByte *pabyBuffer = static_cast<GByte *>(pBuffer);
    3325           1 :             EXPECT_EQ(pabyBuffer[0], 0xFF);
    3326           1 :             EXPECT_EQ(pabyBuffer[1], 0xD8);
    3327           1 :             EXPECT_EQ(pabyBuffer[nNeededSize - 2], 0xFF);
    3328           1 :             EXPECT_EQ(pabyBuffer[nNeededSize - 1], 0xD9);
    3329             :         }
    3330           1 :         VSIFree(pBuffer);
    3331             :     }
    3332             : 
    3333             :     // Cannot subset just one pixel
    3334           1 :     EXPECT_EQ(GDALDatasetReadCompressedData(
    3335             :                   GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 1, 1, 1,
    3336             :                   nullptr, nullptr, nullptr, nullptr),
    3337             :               CE_Failure);
    3338             : 
    3339           1 :     EXPECT_EQ(GDALDatasetReadCompressedData(
    3340             :                   GDALDataset::ToHandle(poSrcDS.get()), "wrong_format", 0, 0,
    3341             :                   20, 20, 1, nullptr, nullptr, nullptr, nullptr),
    3342             :               CE_Failure);
    3343             : }
    3344             : 
    3345             : // Test GDALDataset::GetCompressionFormats() and ReadCompressedData()
    3346           4 : TEST_F(test_gdal, gtiff_ReadCompressedData_jpeg_rgba)
    3347             : {
    3348           1 :     if (GDALGetDriverByName("JPEG") == nullptr)
    3349             :     {
    3350           0 :         GTEST_SKIP() << "JPEG support missing";
    3351             :     }
    3352             : 
    3353             :     GDALDatasetUniquePtr poSrcDS(GDALDataset::FromHandle(
    3354           1 :         GDALDataset::Open((tut::common::data_basedir +
    3355             :                            "/../../gcore/data/stefan_full_rgba_jpeg_contig.tif")
    3356           1 :                               .c_str())));
    3357           1 :     ASSERT_TRUE(poSrcDS);
    3358             : 
    3359             :     const CPLStringList aosRet(GDALDatasetGetCompressionFormats(
    3360           1 :         GDALDataset::ToHandle(poSrcDS.get()), 0, 0, 162, 16, 4, nullptr));
    3361           1 :     EXPECT_EQ(aosRet.size(), 1);
    3362           1 :     if (aosRet.size() == 1)
    3363             :     {
    3364           1 :         EXPECT_STREQ(aosRet[0], "JPEG;colorspace=RGBA");
    3365             :     }
    3366             : 
    3367             :     // Let GDAL allocate buffer
    3368             :     {
    3369           1 :         void *pBuffer = nullptr;
    3370           1 :         size_t nGotSize = 0;
    3371           1 :         char *pszDetailedFormat = nullptr;
    3372           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3373             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 162,
    3374             :                       16, 4, nullptr, &pBuffer, &nGotSize, &pszDetailedFormat),
    3375             :                   CE_None);
    3376           1 :         if (pszDetailedFormat)
    3377             :         {
    3378           1 :             ASSERT_STREQ(pszDetailedFormat,
    3379             :                          "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_"
    3380             :                          "components=4;colorspace=RGBA");
    3381           1 :             VSIFree(pszDetailedFormat);
    3382             :         }
    3383           1 :         VSIFree(pBuffer);
    3384             :     }
    3385             : }
    3386             : 
    3387             : // Test GDALDataset::GetCompressionFormats() and ReadCompressedData()
    3388           4 : TEST_F(test_gdal, jpeg_ReadCompressedData)
    3389             : {
    3390           1 :     if (GDALGetDriverByName("JPEG") == nullptr)
    3391             :     {
    3392           0 :         GTEST_SKIP() << "JPEG support missing";
    3393             :     }
    3394             : 
    3395           1 :     GDALDatasetUniquePtr poSrcDS(GDALDataset::FromHandle(GDALDataset::Open(
    3396           1 :         (tut::common::data_basedir + "/../../gdrivers/data/jpeg/albania.jpg")
    3397           1 :             .c_str())));
    3398           1 :     ASSERT_TRUE(poSrcDS);
    3399             : 
    3400             :     const CPLStringList aosRet(GDALDatasetGetCompressionFormats(
    3401           1 :         GDALDataset::ToHandle(poSrcDS.get()), 0, 0, 361, 260, 3, nullptr));
    3402           1 :     EXPECT_EQ(aosRet.size(), 1);
    3403           1 :     if (aosRet.size() == 1)
    3404             :     {
    3405           1 :         EXPECT_STREQ(aosRet[0],
    3406             :                      "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components="
    3407             :                      "3;subsampling=4:2:0;colorspace=YCbCr");
    3408             :     }
    3409             : 
    3410             :     size_t nUpperBoundSize;
    3411           1 :     EXPECT_EQ(GDALDatasetReadCompressedData(
    3412             :                   GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 361, 260,
    3413             :                   3, nullptr, nullptr, &nUpperBoundSize, nullptr),
    3414             :               CE_None);
    3415           1 :     EXPECT_EQ(nUpperBoundSize, 12574);
    3416             : 
    3417             :     {
    3418           1 :         std::vector<GByte> abyBuffer(nUpperBoundSize);
    3419           1 :         void *pabyBuffer = abyBuffer.data();
    3420           1 :         void **ppabyBuffer = &pabyBuffer;
    3421           1 :         size_t nSize = nUpperBoundSize;
    3422           1 :         char *pszDetailedFormat = nullptr;
    3423           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3424             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 361,
    3425             :                       260, 3, nullptr, ppabyBuffer, &nSize, &pszDetailedFormat),
    3426             :                   CE_None);
    3427           1 :         ASSERT_LT(nSize, nUpperBoundSize);
    3428           1 :         ASSERT_TRUE(*ppabyBuffer == pabyBuffer);
    3429           1 :         EXPECT_TRUE(pszDetailedFormat != nullptr);
    3430           1 :         if (pszDetailedFormat)
    3431             :         {
    3432           1 :             ASSERT_STREQ(pszDetailedFormat,
    3433             :                          "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_"
    3434             :                          "components=3;subsampling=4:2:0;colorspace=YCbCr");
    3435           1 :             VSIFree(pszDetailedFormat);
    3436             :         }
    3437           1 :         EXPECT_EQ(abyBuffer[0], 0xFF);
    3438           1 :         EXPECT_EQ(abyBuffer[1], 0xD8);
    3439           1 :         EXPECT_EQ(abyBuffer[nSize - 2], 0xFF);
    3440           1 :         EXPECT_EQ(abyBuffer[nSize - 1], 0xD9);
    3441             : 
    3442             :         // Buffer larger than needed: OK
    3443           1 :         nSize = nUpperBoundSize + 1;
    3444           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3445             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 361,
    3446             :                       260, 3, nullptr, ppabyBuffer, &nSize, nullptr),
    3447             :                   CE_None);
    3448             : 
    3449             :         // Too small buffer
    3450           1 :         nSize = nUpperBoundSize - 1;
    3451           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3452             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 361,
    3453             :                       260, 3, nullptr, ppabyBuffer, &nSize, nullptr),
    3454             :                   CE_Failure);
    3455             : 
    3456             :         // Missing pointer to size
    3457           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3458             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 361,
    3459             :                       260, 3, nullptr, ppabyBuffer, nullptr, nullptr),
    3460             :                   CE_Failure);
    3461             :     }
    3462             : 
    3463             :     // Let GDAL allocate buffer
    3464             :     {
    3465           1 :         void *pBuffer = nullptr;
    3466           1 :         size_t nSize = nUpperBoundSize;
    3467           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3468             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 361,
    3469             :                       260, 3, nullptr, &pBuffer, &nSize, nullptr),
    3470             :                   CE_None);
    3471           1 :         EXPECT_GT(nSize, 4);
    3472           1 :         EXPECT_LT(nSize, nUpperBoundSize);
    3473           1 :         EXPECT_NE(pBuffer, nullptr);
    3474           1 :         if (pBuffer != nullptr && nSize >= 4 && nSize <= nUpperBoundSize)
    3475             :         {
    3476           1 :             const GByte *pabyBuffer = static_cast<GByte *>(pBuffer);
    3477           1 :             EXPECT_EQ(pabyBuffer[0], 0xFF);
    3478           1 :             EXPECT_EQ(pabyBuffer[1], 0xD8);
    3479           1 :             EXPECT_EQ(pabyBuffer[nSize - 2], 0xFF);
    3480           1 :             EXPECT_EQ(pabyBuffer[nSize - 1], 0xD9);
    3481             :         }
    3482           1 :         VSIFree(pBuffer);
    3483             :     }
    3484             : }
    3485             : 
    3486             : // Test GDALDataset::GetCompressionFormats() and ReadCompressedData()
    3487           4 : TEST_F(test_gdal, jpegxl_ReadCompressedData)
    3488             : {
    3489           1 :     if (GDALGetDriverByName("JPEGXL") == nullptr)
    3490             :     {
    3491           0 :         GTEST_SKIP() << "JPEGXL support missing";
    3492             :     }
    3493             : 
    3494           1 :     GDALDatasetUniquePtr poSrcDS(GDALDataset::FromHandle(GDALDataset::Open(
    3495           1 :         (tut::common::data_basedir + "/../../gdrivers/data/jpegxl/byte.jxl")
    3496           1 :             .c_str())));
    3497           1 :     ASSERT_TRUE(poSrcDS);
    3498             : 
    3499             :     const CPLStringList aosRet(GDALDatasetGetCompressionFormats(
    3500           1 :         GDALDataset::ToHandle(poSrcDS.get()), 0, 0, 20, 20, 1, nullptr));
    3501           1 :     EXPECT_EQ(aosRet.size(), 1);
    3502           1 :     if (aosRet.size() == 1)
    3503             :     {
    3504           1 :         EXPECT_STREQ(aosRet[0], "JXL");
    3505             :     }
    3506             : 
    3507             :     size_t nUpperBoundSize;
    3508           1 :     EXPECT_EQ(GDALDatasetReadCompressedData(
    3509             :                   GDALDataset::ToHandle(poSrcDS.get()), "JXL", 0, 0, 20, 20, 1,
    3510             :                   nullptr, nullptr, &nUpperBoundSize, nullptr),
    3511             :               CE_None);
    3512           1 :     EXPECT_EQ(nUpperBoundSize, 719);
    3513             : 
    3514             :     {
    3515           1 :         std::vector<GByte> abyBuffer(nUpperBoundSize);
    3516           1 :         void *pabyBuffer = abyBuffer.data();
    3517           1 :         void **ppabyBuffer = &pabyBuffer;
    3518           1 :         size_t nSize = nUpperBoundSize;
    3519           1 :         char *pszDetailedFormat = nullptr;
    3520           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3521             :                       GDALDataset::ToHandle(poSrcDS.get()), "JXL", 0, 0, 20, 20,
    3522             :                       1, nullptr, ppabyBuffer, &nSize, &pszDetailedFormat),
    3523             :                   CE_None);
    3524           1 :         ASSERT_LT(nSize, nUpperBoundSize);
    3525           1 :         ASSERT_TRUE(*ppabyBuffer == pabyBuffer);
    3526           1 :         EXPECT_TRUE(pszDetailedFormat != nullptr);
    3527           1 :         if (pszDetailedFormat)
    3528             :         {
    3529           1 :             ASSERT_STREQ(pszDetailedFormat, "JXL");
    3530           1 :             VSIFree(pszDetailedFormat);
    3531             :         }
    3532           1 :         EXPECT_EQ(abyBuffer[0], 0x00);
    3533           1 :         EXPECT_EQ(abyBuffer[1], 0x00);
    3534           1 :         EXPECT_EQ(abyBuffer[2], 0x00);
    3535           1 :         EXPECT_EQ(abyBuffer[3], 0x0C);
    3536           1 :         EXPECT_EQ(abyBuffer[nSize - 2], 0x4C);
    3537           1 :         EXPECT_EQ(abyBuffer[nSize - 1], 0x01);
    3538             : 
    3539             :         // Buffer larger than needed: OK
    3540           1 :         nSize = nUpperBoundSize + 1;
    3541           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3542             :                       GDALDataset::ToHandle(poSrcDS.get()), "JXL", 0, 0, 20, 20,
    3543             :                       1, nullptr, ppabyBuffer, &nSize, nullptr),
    3544             :                   CE_None);
    3545             : 
    3546             :         // Too small buffer
    3547           1 :         nSize = nUpperBoundSize - 1;
    3548           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3549             :                       GDALDataset::ToHandle(poSrcDS.get()), "JXL", 0, 0, 20, 20,
    3550             :                       1, nullptr, ppabyBuffer, &nSize, nullptr),
    3551             :                   CE_Failure);
    3552             : 
    3553             :         // Missing pointer to size
    3554           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3555             :                       GDALDataset::ToHandle(poSrcDS.get()), "JXL", 0, 0, 20, 20,
    3556             :                       1, nullptr, ppabyBuffer, nullptr, nullptr),
    3557             :                   CE_Failure);
    3558             :     }
    3559             : 
    3560             :     // Let GDAL allocate buffer
    3561             :     {
    3562           1 :         void *pBuffer = nullptr;
    3563           1 :         size_t nSize = nUpperBoundSize;
    3564           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3565             :                       GDALDataset::ToHandle(poSrcDS.get()), "JXL", 0, 0, 20, 20,
    3566             :                       1, nullptr, &pBuffer, &nSize, nullptr),
    3567             :                   CE_None);
    3568           1 :         EXPECT_GT(nSize, 6);
    3569           1 :         EXPECT_LT(nSize, nUpperBoundSize);
    3570           1 :         EXPECT_NE(pBuffer, nullptr);
    3571           1 :         if (pBuffer != nullptr && nSize >= 6 && nSize <= nUpperBoundSize)
    3572             :         {
    3573           1 :             const GByte *pabyBuffer = static_cast<GByte *>(pBuffer);
    3574           1 :             EXPECT_EQ(pabyBuffer[0], 0x00);
    3575           1 :             EXPECT_EQ(pabyBuffer[1], 0x00);
    3576           1 :             EXPECT_EQ(pabyBuffer[2], 0x00);
    3577           1 :             EXPECT_EQ(pabyBuffer[3], 0x0C);
    3578           1 :             EXPECT_EQ(pabyBuffer[nSize - 2], 0x4C);
    3579           1 :             EXPECT_EQ(pabyBuffer[nSize - 1], 0x01);
    3580             :         }
    3581           1 :         VSIFree(pBuffer);
    3582             :     }
    3583             : }
    3584             : 
    3585             : // Test GDALDataset::GetCompressionFormats() and ReadCompressedData()
    3586           4 : TEST_F(test_gdal, jpegxl_jpeg_compatible_ReadCompressedData)
    3587             : {
    3588           1 :     auto poDrv = GDALDriver::FromHandle(GDALGetDriverByName("JPEGXL"));
    3589           1 :     if (poDrv == nullptr)
    3590             :     {
    3591           0 :         GTEST_SKIP() << "JPEGXL support missing";
    3592             :     }
    3593             : 
    3594           1 :     GDALDatasetUniquePtr poSrcDS(GDALDataset::FromHandle(GDALDataset::Open(
    3595           1 :         (tut::common::data_basedir +
    3596             :          "/../../gdrivers/data/jpegxl/exif_orientation/F1.jxl")
    3597           1 :             .c_str())));
    3598           1 :     ASSERT_TRUE(poSrcDS);
    3599             : 
    3600             :     const CPLStringList aosRet(GDALDatasetGetCompressionFormats(
    3601           1 :         GDALDataset::ToHandle(poSrcDS.get()), 0, 0, 3, 5, 1, nullptr));
    3602           1 :     EXPECT_EQ(aosRet.size(), 2);
    3603           1 :     if (aosRet.size() == 2)
    3604             :     {
    3605           1 :         EXPECT_STREQ(aosRet[0], "JXL");
    3606           1 :         EXPECT_STREQ(aosRet[1], "JPEG");
    3607             :     }
    3608             : 
    3609             :     size_t nUpperBoundSize;
    3610           1 :     EXPECT_EQ(GDALDatasetReadCompressedData(
    3611             :                   GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 3, 5, 1,
    3612             :                   nullptr, nullptr, &nUpperBoundSize, nullptr),
    3613             :               CE_None);
    3614           1 :     EXPECT_EQ(nUpperBoundSize, 235);
    3615             : 
    3616             :     {
    3617           1 :         std::vector<GByte> abyBuffer(nUpperBoundSize);
    3618           1 :         void *pabyBuffer = abyBuffer.data();
    3619           1 :         void **ppabyBuffer = &pabyBuffer;
    3620           1 :         size_t nSize = nUpperBoundSize;
    3621           1 :         char *pszDetailedFormat = nullptr;
    3622           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3623             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 3, 5,
    3624             :                       1, nullptr, ppabyBuffer, &nSize, &pszDetailedFormat),
    3625             :                   CE_None);
    3626           1 :         ASSERT_LE(nSize, nUpperBoundSize);
    3627           1 :         ASSERT_TRUE(*ppabyBuffer == pabyBuffer);
    3628           1 :         EXPECT_TRUE(pszDetailedFormat != nullptr);
    3629           1 :         if (pszDetailedFormat)
    3630             :         {
    3631           1 :             ASSERT_STREQ(pszDetailedFormat,
    3632             :                          "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_"
    3633             :                          "components=1;colorspace=unknown");
    3634           1 :             VSIFree(pszDetailedFormat);
    3635             :         }
    3636           1 :         EXPECT_EQ(abyBuffer[0], 0xFF);
    3637           1 :         EXPECT_EQ(abyBuffer[1], 0xD8);
    3638           1 :         EXPECT_EQ(abyBuffer[nSize - 2], 0xFF);
    3639           1 :         EXPECT_EQ(abyBuffer[nSize - 1], 0xD9);
    3640             : 
    3641             :         // Buffer larger than needed: OK
    3642           1 :         nSize = nUpperBoundSize + 1;
    3643           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3644             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 3, 5,
    3645             :                       1, nullptr, ppabyBuffer, &nSize, nullptr),
    3646             :                   CE_None);
    3647             : 
    3648             :         // Too small buffer
    3649           1 :         nSize = nUpperBoundSize - 1;
    3650           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3651             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 3, 5,
    3652             :                       1, nullptr, ppabyBuffer, &nSize, nullptr),
    3653             :                   CE_Failure);
    3654             : 
    3655             :         // Missing pointer to size
    3656           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3657             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 3, 5,
    3658             :                       1, nullptr, ppabyBuffer, nullptr, nullptr),
    3659             :                   CE_Failure);
    3660             :     }
    3661             : 
    3662             :     // Let GDAL allocate buffer
    3663             :     {
    3664           1 :         void *pBuffer = nullptr;
    3665           1 :         size_t nSize = nUpperBoundSize;
    3666           1 :         EXPECT_EQ(GDALDatasetReadCompressedData(
    3667             :                       GDALDataset::ToHandle(poSrcDS.get()), "JPEG", 0, 0, 3, 5,
    3668             :                       1, nullptr, &pBuffer, &nSize, nullptr),
    3669             :                   CE_None);
    3670           1 :         EXPECT_GT(nSize, 4);
    3671           1 :         EXPECT_LE(nSize, nUpperBoundSize);
    3672           1 :         EXPECT_NE(pBuffer, nullptr);
    3673           1 :         if (pBuffer != nullptr && nSize >= 4 && nSize <= nUpperBoundSize)
    3674             :         {
    3675           1 :             const GByte *pabyBuffer = static_cast<GByte *>(pBuffer);
    3676           1 :             EXPECT_EQ(pabyBuffer[0], 0xFF);
    3677           1 :             EXPECT_EQ(pabyBuffer[1], 0xD8);
    3678           1 :             EXPECT_EQ(pabyBuffer[nSize - 2], 0xFF);
    3679           1 :             EXPECT_EQ(pabyBuffer[nSize - 1], 0xD9);
    3680             :         }
    3681           1 :         VSIFree(pBuffer);
    3682             :     }
    3683             : }
    3684             : 
    3685             : // Test GDAL_OF_SHARED flag and open options
    3686           4 : TEST_F(test_gdal, open_shared_open_options)
    3687             : {
    3688           1 :     CPLErrorReset();
    3689           1 :     const char *const apszOpenOptions[] = {"OVERVIEW_LEVEL=NONE", nullptr};
    3690             :     {
    3691             :         GDALDataset *poDS1 =
    3692           1 :             GDALDataset::Open(GCORE_DATA_DIR "rgbsmall.tif", GDAL_OF_SHARED,
    3693           1 :                               nullptr, apszOpenOptions);
    3694             :         GDALDataset *poDS2 =
    3695           1 :             GDALDataset::Open(GCORE_DATA_DIR "rgbsmall.tif", GDAL_OF_SHARED,
    3696           1 :                               nullptr, apszOpenOptions);
    3697           1 :         EXPECT_EQ(CPLGetLastErrorType(), CE_None);
    3698           1 :         EXPECT_NE(poDS1, nullptr);
    3699           1 :         EXPECT_NE(poDS2, nullptr);
    3700           1 :         EXPECT_EQ(poDS1, poDS2);
    3701           1 :         GDALClose(poDS1);
    3702           1 :         GDALClose(poDS2);
    3703             :     }
    3704             :     {
    3705             :         GDALDataset *poDS1 =
    3706           1 :             GDALDataset::Open(GCORE_DATA_DIR "rgbsmall.tif", GDAL_OF_SHARED,
    3707           1 :                               nullptr, apszOpenOptions);
    3708           1 :         GDALDataset *poDS2 = GDALDataset::Open(
    3709           1 :             GCORE_DATA_DIR "rgbsmall.tif", GDAL_OF_SHARED, nullptr, nullptr);
    3710             :         GDALDataset *poDS3 =
    3711           1 :             GDALDataset::Open(GCORE_DATA_DIR "rgbsmall.tif", GDAL_OF_SHARED,
    3712           1 :                               nullptr, apszOpenOptions);
    3713           1 :         EXPECT_EQ(CPLGetLastErrorType(), CE_None);
    3714           1 :         EXPECT_NE(poDS1, nullptr);
    3715           1 :         EXPECT_NE(poDS2, nullptr);
    3716           1 :         EXPECT_NE(poDS3, nullptr);
    3717           1 :         EXPECT_NE(poDS1, poDS2);
    3718           1 :         EXPECT_EQ(poDS1, poDS3);
    3719           1 :         GDALClose(poDS1);
    3720           1 :         GDALClose(poDS2);
    3721           1 :         GDALClose(poDS3);
    3722             :     }
    3723             :     {
    3724           1 :         GDALDataset *poDS1 = GDALDataset::Open(GCORE_DATA_DIR "rgbsmall.tif",
    3725             :                                                GDAL_OF_SHARED | GDAL_OF_UPDATE,
    3726           1 :                                                nullptr, apszOpenOptions);
    3727             :         // We allow to re-use a shared dataset in update mode when requesting it in read-only
    3728             :         GDALDataset *poDS2 =
    3729           1 :             GDALDataset::Open(GCORE_DATA_DIR "rgbsmall.tif", GDAL_OF_SHARED,
    3730           1 :                               nullptr, apszOpenOptions);
    3731           1 :         EXPECT_EQ(CPLGetLastErrorType(), CE_None);
    3732           1 :         EXPECT_NE(poDS1, nullptr);
    3733           1 :         EXPECT_NE(poDS2, nullptr);
    3734           1 :         EXPECT_EQ(poDS1, poDS2);
    3735           1 :         GDALClose(poDS1);
    3736           1 :         GDALClose(poDS2);
    3737             :     }
    3738             :     {
    3739           1 :         GDALDataset *poDS1 = GDALDataset::Open(
    3740           1 :             GCORE_DATA_DIR "rgbsmall.tif", GDAL_OF_SHARED, nullptr, nullptr);
    3741             :         GDALDataset *poDS2 =
    3742           1 :             GDALDataset::Open(GCORE_DATA_DIR "rgbsmall.tif", GDAL_OF_SHARED,
    3743           1 :                               nullptr, apszOpenOptions);
    3744             :         GDALDataset *poDS3 =
    3745           1 :             GDALDataset::Open(GCORE_DATA_DIR "rgbsmall.tif", GDAL_OF_SHARED,
    3746           1 :                               nullptr, apszOpenOptions);
    3747           1 :         EXPECT_EQ(CPLGetLastErrorType(), CE_None);
    3748           1 :         EXPECT_NE(poDS1, nullptr);
    3749           1 :         EXPECT_NE(poDS2, nullptr);
    3750           1 :         EXPECT_NE(poDS3, nullptr);
    3751           1 :         EXPECT_NE(poDS1, poDS2);
    3752           1 :         EXPECT_EQ(poDS2, poDS3);
    3753           1 :         GDALClose(poDS1);
    3754           1 :         GDALClose(poDS2);
    3755           1 :         GDALClose(poDS3);
    3756             :     }
    3757           1 : }
    3758             : 
    3759             : // Test DropCache() to check that no data is saved on disk
    3760           4 : TEST_F(test_gdal, drop_cache)
    3761             : {
    3762           1 :     CPLErrorReset();
    3763             :     {
    3764           1 :         GDALDriverManager *gdalDriverManager = GetGDALDriverManager();
    3765           1 :         if (!gdalDriverManager)
    3766           0 :             return;
    3767           1 :         GDALDriver *enviDriver = gdalDriverManager->GetDriverByName("ENVI");
    3768           1 :         if (!enviDriver)
    3769           0 :             return;
    3770           1 :         const char *enviOptions[] = {"SUFFIX=ADD", "INTERLEAVE=BIL", nullptr};
    3771             : 
    3772           1 :         const char *filename = GCORE_DATA_DIR "test_drop_cache.bil";
    3773             : 
    3774             :         auto poDS = std::unique_ptr<GDALDataset>(enviDriver->Create(
    3775           1 :             filename, 1, 1, 1, GDALDataType::GDT_Float32, enviOptions));
    3776           1 :         if (!poDS)
    3777           0 :             return;
    3778           1 :         poDS->GetRasterBand(1)->Fill(1);
    3779           1 :         poDS->DropCache();
    3780           1 :         poDS.reset();
    3781             : 
    3782           1 :         poDS.reset(
    3783             :             GDALDataset::Open(filename, GDAL_OF_SHARED, nullptr, nullptr));
    3784           1 :         if (!poDS)
    3785           0 :             return;
    3786             : 
    3787           1 :         EXPECT_EQ(GDALChecksumImage(poDS->GetRasterBand(1), 0, 0, 1, 1), 0);
    3788           1 :         poDS->MarkSuppressOnClose();
    3789           1 :         poDS.reset();
    3790             :     }
    3791             : }
    3792             : 
    3793             : // Test gdal::gcp class
    3794           4 : TEST_F(test_gdal, gdal_gcp_class)
    3795             : {
    3796             :     {
    3797           2 :         gdal::GCP gcp;
    3798           1 :         EXPECT_STREQ(gcp.Id(), "");
    3799           1 :         EXPECT_STREQ(gcp.Info(), "");
    3800           1 :         EXPECT_EQ(gcp.Pixel(), 0.0);
    3801           1 :         EXPECT_EQ(gcp.Line(), 0.0);
    3802           1 :         EXPECT_EQ(gcp.X(), 0.0);
    3803           1 :         EXPECT_EQ(gcp.Y(), 0.0);
    3804           1 :         EXPECT_EQ(gcp.Z(), 0.0);
    3805             :     }
    3806             :     {
    3807           2 :         gdal::GCP gcp("id", "info", 1.5, 2.5, 3.5, 4.5, 5.5);
    3808           1 :         EXPECT_STREQ(gcp.Id(), "id");
    3809           1 :         EXPECT_STREQ(gcp.Info(), "info");
    3810           1 :         EXPECT_EQ(gcp.Pixel(), 1.5);
    3811           1 :         EXPECT_EQ(gcp.Line(), 2.5);
    3812           1 :         EXPECT_EQ(gcp.X(), 3.5);
    3813           1 :         EXPECT_EQ(gcp.Y(), 4.5);
    3814           1 :         EXPECT_EQ(gcp.Z(), 5.5);
    3815             : 
    3816           1 :         gcp.SetId("id2");
    3817           1 :         gcp.SetInfo("info2");
    3818           1 :         gcp.Pixel() = -1.5;
    3819           1 :         gcp.Line() = -2.5;
    3820           1 :         gcp.X() = -3.5;
    3821           1 :         gcp.Y() = -4.5;
    3822           1 :         gcp.Z() = -5.5;
    3823           1 :         EXPECT_STREQ(gcp.Id(), "id2");
    3824           1 :         EXPECT_STREQ(gcp.Info(), "info2");
    3825           1 :         EXPECT_EQ(gcp.Pixel(), -1.5);
    3826           1 :         EXPECT_EQ(gcp.Line(), -2.5);
    3827           1 :         EXPECT_EQ(gcp.X(), -3.5);
    3828           1 :         EXPECT_EQ(gcp.Y(), -4.5);
    3829           1 :         EXPECT_EQ(gcp.Z(), -5.5);
    3830             : 
    3831             :         {
    3832           2 :             gdal::GCP gcp_copy(gcp);
    3833           1 :             EXPECT_STREQ(gcp_copy.Id(), "id2");
    3834           1 :             EXPECT_STREQ(gcp_copy.Info(), "info2");
    3835           1 :             EXPECT_EQ(gcp_copy.Pixel(), -1.5);
    3836           1 :             EXPECT_EQ(gcp_copy.Line(), -2.5);
    3837           1 :             EXPECT_EQ(gcp_copy.X(), -3.5);
    3838           1 :             EXPECT_EQ(gcp_copy.Y(), -4.5);
    3839           1 :             EXPECT_EQ(gcp_copy.Z(), -5.5);
    3840             :         }
    3841             : 
    3842             :         {
    3843           2 :             gdal::GCP gcp_copy;
    3844           1 :             gcp_copy = gcp;
    3845           1 :             EXPECT_STREQ(gcp_copy.Id(), "id2");
    3846           1 :             EXPECT_STREQ(gcp_copy.Info(), "info2");
    3847           1 :             EXPECT_EQ(gcp_copy.Pixel(), -1.5);
    3848           1 :             EXPECT_EQ(gcp_copy.Line(), -2.5);
    3849           1 :             EXPECT_EQ(gcp_copy.X(), -3.5);
    3850           1 :             EXPECT_EQ(gcp_copy.Y(), -4.5);
    3851           1 :             EXPECT_EQ(gcp_copy.Z(), -5.5);
    3852             :         }
    3853             : 
    3854             :         {
    3855           2 :             gdal::GCP gcp_copy(gcp);
    3856           2 :             gdal::GCP gcp_from_moved(std::move(gcp_copy));
    3857           1 :             EXPECT_STREQ(gcp_from_moved.Id(), "id2");
    3858           1 :             EXPECT_STREQ(gcp_from_moved.Info(), "info2");
    3859           1 :             EXPECT_EQ(gcp_from_moved.Pixel(), -1.5);
    3860           1 :             EXPECT_EQ(gcp_from_moved.Line(), -2.5);
    3861           1 :             EXPECT_EQ(gcp_from_moved.X(), -3.5);
    3862           1 :             EXPECT_EQ(gcp_from_moved.Y(), -4.5);
    3863           1 :             EXPECT_EQ(gcp_from_moved.Z(), -5.5);
    3864             :         }
    3865             : 
    3866             :         {
    3867           2 :             gdal::GCP gcp_copy(gcp);
    3868           2 :             gdal::GCP gcp_from_moved;
    3869           1 :             gcp_from_moved = std::move(gcp_copy);
    3870           1 :             EXPECT_STREQ(gcp_from_moved.Id(), "id2");
    3871           1 :             EXPECT_STREQ(gcp_from_moved.Info(), "info2");
    3872           1 :             EXPECT_EQ(gcp_from_moved.Pixel(), -1.5);
    3873           1 :             EXPECT_EQ(gcp_from_moved.Line(), -2.5);
    3874           1 :             EXPECT_EQ(gcp_from_moved.X(), -3.5);
    3875           1 :             EXPECT_EQ(gcp_from_moved.Y(), -4.5);
    3876           1 :             EXPECT_EQ(gcp_from_moved.Z(), -5.5);
    3877             :         }
    3878             : 
    3879             :         {
    3880           1 :             const GDAL_GCP *c_gcp = gcp.c_ptr();
    3881           1 :             EXPECT_STREQ(c_gcp->pszId, "id2");
    3882           1 :             EXPECT_STREQ(c_gcp->pszInfo, "info2");
    3883           1 :             EXPECT_EQ(c_gcp->dfGCPPixel, -1.5);
    3884           1 :             EXPECT_EQ(c_gcp->dfGCPLine, -2.5);
    3885           1 :             EXPECT_EQ(c_gcp->dfGCPX, -3.5);
    3886           1 :             EXPECT_EQ(c_gcp->dfGCPY, -4.5);
    3887           1 :             EXPECT_EQ(c_gcp->dfGCPZ, -5.5);
    3888             : 
    3889           2 :             const gdal::GCP gcp_from_c(*c_gcp);
    3890           1 :             EXPECT_STREQ(gcp_from_c.Id(), "id2");
    3891           1 :             EXPECT_STREQ(gcp_from_c.Info(), "info2");
    3892           1 :             EXPECT_EQ(gcp_from_c.Pixel(), -1.5);
    3893           1 :             EXPECT_EQ(gcp_from_c.Line(), -2.5);
    3894           1 :             EXPECT_EQ(gcp_from_c.X(), -3.5);
    3895           1 :             EXPECT_EQ(gcp_from_c.Y(), -4.5);
    3896           1 :             EXPECT_EQ(gcp_from_c.Z(), -5.5);
    3897             :         }
    3898             :     }
    3899             : 
    3900             :     {
    3901             :         const std::vector<gdal::GCP> gcps{
    3902             :             gdal::GCP{nullptr, nullptr, 0, 0, 0, 0, 0},
    3903           4 :             gdal::GCP{"id", "info", 1.5, 2.5, 3.5, 4.5, 5.5}};
    3904             : 
    3905           1 :         const GDAL_GCP *c_gcps = gdal::GCP::c_ptr(gcps);
    3906           1 :         EXPECT_STREQ(c_gcps[1].pszId, "id");
    3907           1 :         EXPECT_STREQ(c_gcps[1].pszInfo, "info");
    3908           1 :         EXPECT_EQ(c_gcps[1].dfGCPPixel, 1.5);
    3909           1 :         EXPECT_EQ(c_gcps[1].dfGCPLine, 2.5);
    3910           1 :         EXPECT_EQ(c_gcps[1].dfGCPX, 3.5);
    3911           1 :         EXPECT_EQ(c_gcps[1].dfGCPY, 4.5);
    3912           1 :         EXPECT_EQ(c_gcps[1].dfGCPZ, 5.5);
    3913             : 
    3914             :         const auto gcps_from_c =
    3915           1 :             gdal::GCP::fromC(c_gcps, static_cast<int>(gcps.size()));
    3916           1 :         ASSERT_EQ(gcps_from_c.size(), gcps.size());
    3917           3 :         for (size_t i = 0; i < gcps.size(); ++i)
    3918             :         {
    3919           2 :             EXPECT_STREQ(gcps_from_c[i].Id(), gcps[i].Id());
    3920           2 :             EXPECT_STREQ(gcps_from_c[i].Info(), gcps[i].Info());
    3921           2 :             EXPECT_EQ(gcps_from_c[i].Pixel(), gcps[i].Pixel());
    3922           2 :             EXPECT_EQ(gcps_from_c[i].Line(), gcps[i].Line());
    3923           2 :             EXPECT_EQ(gcps_from_c[i].X(), gcps[i].X());
    3924           2 :             EXPECT_EQ(gcps_from_c[i].Y(), gcps[i].Y());
    3925           2 :             EXPECT_EQ(gcps_from_c[i].Z(), gcps[i].Z());
    3926             :         }
    3927             :     }
    3928             : }
    3929             : 
    3930             : }  // namespace

Generated by: LCOV version 1.14