LCOV - code coverage report
Current view: top level - autotest/cpp - test_gdal.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 3308 3356 98.6 %
Date: 2026-09-22 20:07:52 Functions: 377 381 99.0 %

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

Generated by: LCOV version 1.14