LCOV - code coverage report
Current view: top level - autotest/cpp - test_gdal.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 2376 2415 98.4 %
Date: 2024-11-21 22:18:42 Functions: 294 298 98.7 %

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

Generated by: LCOV version 1.14