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

Generated by: LCOV version 1.14