LCOV - code coverage report
Current view: top level - autotest/cpp - test_gdal.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 3180 3227 98.5 %
Date: 2025-12-29 15:50:47 Functions: 357 361 98.9 %

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

Generated by: LCOV version 1.14