LCOV - code coverage report
Current view: top level - autotest/cpp - test_gdal.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 2938 2984 98.5 %
Date: 2025-08-01 10:10:57 Functions: 341 345 98.8 %

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

Generated by: LCOV version 1.14