LCOV - code coverage report
Current view: top level - autotest/cpp - test_ogr_wkb.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 207 207 100.0 %
Date: 2024-11-21 22:18:42 Functions: 49 49 100.0 %

          Line data    Source code
       1             : ///////////////////////////////////////////////////////////////////////////////
       2             : //
       3             : // Project:  C++ Test Suite for GDAL/OGR
       4             : // Purpose:  Test ogr_wkb.h
       5             : // Author:   Even Rouault <even.rouault at spatialys.com>
       6             : //
       7             : ///////////////////////////////////////////////////////////////////////////////
       8             : // Copyright (c) 2023, Even Rouault <even.rouault at spatialys.com>
       9             : /*
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "gdal_unit_test.h"
      14             : 
      15             : #include "ogr_geometry.h"
      16             : #include "ogr_wkb.h"
      17             : 
      18             : #include "gtest_include.h"
      19             : 
      20             : #include <limits>
      21             : 
      22             : namespace
      23             : {
      24             : 
      25             : struct test_ogr_wkb : public ::testing::Test
      26             : {
      27             : };
      28             : 
      29             : class OGRWKBGetEnvelopeFixture
      30             :     : public test_ogr_wkb,
      31             :       public ::testing::WithParamInterface<std::tuple<
      32             :           const char *, double, double, double, double, const char *>>
      33             : {
      34             :     static constexpr double INF = std::numeric_limits<double>::infinity();
      35             : 
      36             :   public:
      37             :     static std::vector<
      38             :         std::tuple<const char *, double, double, double, double, const char *>>
      39           1 :     GetTupleValues()
      40             :     {
      41             :         return {
      42             :             std::make_tuple("POINT(1 2)", 1, 2, 1, 2, "POINT"),
      43             :             std::make_tuple("POINT EMPTY", INF, INF, -INF, -INF, "POINT_EMPTY"),
      44             :             std::make_tuple("POINT Z (1 2 3)", 1, 2, 1, 2, "POINT_3D"),
      45             :             std::make_tuple("LINESTRING(3 4,1 2)", 1, 2, 3, 4, "LINESTRING"),
      46             :             std::make_tuple("LINESTRING EMPTY", INF, INF, -INF, -INF,
      47             :                             "LINESTRING_EMPTY"),
      48             :             std::make_tuple("LINESTRING Z (3 4 5,1 2 6)", 1, 2, 3, 4,
      49             :                             "LINESTRING_3D"),
      50             :             std::make_tuple("POLYGON((0 1,0 2,3 2,0 1))", 0, 1, 3, 2,
      51             :                             "POLYGON"),
      52             :             std::make_tuple("POLYGON EMPTY", INF, INF, -INF, -INF,
      53             :                             "POLYGON_EMPTY"),
      54             :             std::make_tuple("POLYGON Z ((0 1 10,0 2 20,3 2 20,0 1 10))", 0, 1,
      55             :                             3, 2, "POLYGON_3D"),
      56             :             std::make_tuple("MULTIPOINT((1 2),(3 4))", 1, 2, 3, 4,
      57             :                             "MULTIPOINT"),
      58             :             std::make_tuple("MULTIPOINT EMPTY", INF, INF, -INF, -INF,
      59             :                             "MULTIPOINT_EMPTY"),
      60             :             std::make_tuple("MULTIPOINT Z ((1 2 10),(3 4 20))", 1, 2, 3, 4,
      61             :                             "MULTIPOINT_3D"),
      62             :             std::make_tuple("MULTILINESTRING((3 4,1 2),(5 6,7 8))", 1, 2, 7, 8,
      63             :                             "MULTILINESTRING"),
      64             :             std::make_tuple("MULTILINESTRING EMPTY", INF, INF, -INF, -INF,
      65             :                             "MULTILINESTRING_EMPTY"),
      66             :             std::make_tuple(
      67             :                 "MULTILINESTRING Z ((3 4 10,1 2 20),(5 6 10,7 8 20))", 1, 2, 7,
      68             :                 8, "MULTILINESTRING_3D"),
      69             :             std::make_tuple(
      70             :                 "MULTIPOLYGON(((0 1,0 2,3 2,0 1)),((0 -1,0 -2,-3 -2,0 -1)))",
      71             :                 -3, -2, 3, 2, "MULTIPOLYGON"),
      72             :             std::make_tuple("MULTIPOLYGON EMPTY", INF, INF, -INF, -INF,
      73             :                             "MULTIPOLYGON_EMPTY"),
      74             :             std::make_tuple("MULTIPOLYGON Z (((0 1 10,0 2 20,3 2 20,0 1 "
      75             :                             "10)),((0 -1 -10,0 -2 -20,-3 -2 -20,0 -1 -10)))",
      76             :                             -3, -2, 3, 2, "MULTIPOLYGON_3D"),
      77             :             std::make_tuple("GEOMETRYCOLLECTION(POINT(1 2),POINT(3 4))", 1, 2,
      78             :                             3, 4, "GEOMETRYCOLLECTION"),
      79             :             std::make_tuple("CIRCULARSTRING(0 10,1 11,2 10)", 0, 10, 2, 11,
      80             :                             "CIRCULARSTRING"),
      81             :             std::make_tuple("COMPOUNDCURVE((3 4,1 2))", 1, 2, 3, 4,
      82             :                             "COMPOUNDCURVE"),
      83             :             std::make_tuple("CURVEPOLYGON((0 1,0 2,3 2,0 1))", 0, 1, 3, 2,
      84             :                             "CURVEPOLYGON"),
      85             :             std::make_tuple("MULTICURVE((3 4,1 2),(5 6,7 8))", 1, 2, 7, 8,
      86             :                             "MULTICURVE"),
      87             :             std::make_tuple(
      88             :                 "MULTISURFACE(((0 1,0 2,3 2,0 1)),((0 -1,0 -2,-3 -2,0 -1)))",
      89             :                 -3, -2, 3, 2, "MULTISURFACE"),
      90             :             std::make_tuple("TRIANGLE((0 1,0 2,3 2,0 1))", 0, 1, 3, 2,
      91             :                             "TRIANGLE"),
      92             :             std::make_tuple("POLYHEDRALSURFACE(((0 1,0 2,3 2,0 1)))", 0, 1, 3,
      93             :                             2, "POLYHEDRALSURFACE"),
      94             :             std::make_tuple("TIN(((0 1,0 2,3 2,0 1)))", 0, 1, 3, 2, "TIN"),
      95           1 :         };
      96             :     }
      97             : };
      98             : 
      99          55 : TEST_P(OGRWKBGetEnvelopeFixture, test)
     100             : {
     101          27 :     const char *pszInput = std::get<0>(GetParam());
     102          27 :     const double dfExpectedMinX = std::get<1>(GetParam());
     103          27 :     const double dfExpectedMinY = std::get<2>(GetParam());
     104          27 :     const double dfExpectedMaxX = std::get<3>(GetParam());
     105          27 :     const double dfExpectedMaxY = std::get<4>(GetParam());
     106             : 
     107          27 :     OGRGeometry *poGeom = nullptr;
     108          27 :     ASSERT_EQ(OGRGeometryFactory::createFromWkt(pszInput, nullptr, &poGeom),
     109             :               OGRERR_NONE);
     110          27 :     ASSERT_TRUE(poGeom != nullptr);
     111          54 :     std::vector<GByte> abyWkb(poGeom->WkbSize());
     112          27 :     poGeom->exportToWkb(wkbNDR, abyWkb.data(), wkbVariantIso);
     113          27 :     delete poGeom;
     114          27 :     OGREnvelope sEnvelope;
     115          27 :     EXPECT_EQ(OGRWKBGetBoundingBox(abyWkb.data(), abyWkb.size(), sEnvelope),
     116             :               true);
     117          27 :     EXPECT_EQ(sEnvelope.MinX, dfExpectedMinX);
     118          27 :     EXPECT_EQ(sEnvelope.MinY, dfExpectedMinY);
     119          27 :     EXPECT_EQ(sEnvelope.MaxX, dfExpectedMaxX);
     120          27 :     EXPECT_EQ(sEnvelope.MaxY, dfExpectedMaxY);
     121             : }
     122             : 
     123          56 : INSTANTIATE_TEST_SUITE_P(
     124             :     test_ogr_wkb, OGRWKBGetEnvelopeFixture,
     125             :     ::testing::ValuesIn(OGRWKBGetEnvelopeFixture::GetTupleValues()),
     126             :     [](const ::testing::TestParamInfo<OGRWKBGetEnvelopeFixture::ParamType>
     127             :            &l_info) { return std::get<5>(l_info.param); });
     128             : 
     129             : class OGRWKBGetEnvelope3DFixture
     130             :     : public test_ogr_wkb,
     131             :       public ::testing::WithParamInterface<
     132             :           std::tuple<const char *, double, double, double, double, double,
     133             :                      double, const char *>>
     134             : {
     135             :     static constexpr double INF = std::numeric_limits<double>::infinity();
     136             : 
     137             :   public:
     138             :     static std::vector<std::tuple<const char *, double, double, double, double,
     139             :                                   double, double, const char *>>
     140           1 :     GetTupleValues()
     141             :     {
     142             :         return {
     143             :             std::make_tuple("POINT(1 2)", 1, 2, INF, 1, 2, -INF, "POINT"),
     144             :             std::make_tuple("POINT EMPTY", INF, INF, INF, -INF, -INF, -INF,
     145             :                             "POINT_EMPTY"),
     146             :             std::make_tuple("POINT Z (1 2 3)", 1, 2, 3, 1, 2, 3, "POINT_3D"),
     147             :             std::make_tuple("LINESTRING(3 4,1 2)", 1, 2, INF, 3, 4, -INF,
     148             :                             "LINESTRING"),
     149             :             std::make_tuple("LINESTRING EMPTY", INF, INF, INF, -INF, -INF, -INF,
     150             :                             "LINESTRING_EMPTY"),
     151             :             std::make_tuple("LINESTRING Z (3 4 5,1 2 6)", 1, 2, 5, 3, 4, 6,
     152             :                             "LINESTRING_3D"),
     153             :             std::make_tuple("POLYGON((0 1,0 2,3 2,0 1))", 0, 1, INF, 3, 2, -INF,
     154             :                             "POLYGON"),
     155             :             std::make_tuple("POLYGON EMPTY", INF, INF, INF, -INF, -INF, -INF,
     156             :                             "POLYGON_EMPTY"),
     157             :             std::make_tuple("POLYGON Z ((0 1 10,0 2 20,3 2 20,0 1 10))", 0, 1,
     158             :                             10, 3, 2, 20, "POLYGON_3D"),
     159             :             std::make_tuple("MULTIPOINT((1 2),(3 4))", 1, 2, INF, 3, 4, -INF,
     160             :                             "MULTIPOINT"),
     161             :             std::make_tuple("MULTIPOINT EMPTY", INF, INF, INF, -INF, -INF, -INF,
     162             :                             "MULTIPOINT_EMPTY"),
     163             :             std::make_tuple("MULTIPOINT Z ((1 2 10),(3 4 20))", 1, 2, 10, 3, 4,
     164             :                             20, "MULTIPOINT_3D"),
     165             :             std::make_tuple("MULTILINESTRING((3 4,1 2),(5 6,7 8))", 1, 2, INF,
     166             :                             7, 8, -INF, "MULTILINESTRING"),
     167             :             std::make_tuple("MULTILINESTRING EMPTY", INF, INF, INF, -INF, -INF,
     168             :                             -INF, "MULTILINESTRING_EMPTY"),
     169             :             std::make_tuple(
     170             :                 "MULTILINESTRING Z ((3 4 10,1 2 20),(5 6 10,7 8 20))", 1, 2, 10,
     171             :                 7, 8, 20, "MULTILINESTRING_3D"),
     172             :             std::make_tuple(
     173             :                 "MULTIPOLYGON(((0 1,0 2,3 2,0 1)),((0 -1,0 -2,-3 -2,0 -1)))",
     174             :                 -3, -2, INF, 3, 2, -INF, "MULTIPOLYGON"),
     175             :             std::make_tuple("MULTIPOLYGON EMPTY", INF, INF, INF, -INF, -INF,
     176             :                             -INF, "MULTIPOLYGON_EMPTY"),
     177             :             std::make_tuple("MULTIPOLYGON Z (((0 1 10,0 2 20,3 2 20,0 1 "
     178             :                             "10)),((0 -1 -10,0 -2 -20,-3 -2 -20,0 -1 -10)))",
     179             :                             -3, -2, -20, 3, 2, 20, "MULTIPOLYGON_3D"),
     180           1 :         };
     181             :     }
     182             : };
     183             : 
     184          37 : TEST_P(OGRWKBGetEnvelope3DFixture, test)
     185             : {
     186          18 :     const char *pszInput = std::get<0>(GetParam());
     187          18 :     const double dfExpectedMinX = std::get<1>(GetParam());
     188          18 :     const double dfExpectedMinY = std::get<2>(GetParam());
     189          18 :     const double dfExpectedMinZ = std::get<3>(GetParam());
     190          18 :     const double dfExpectedMaxX = std::get<4>(GetParam());
     191          18 :     const double dfExpectedMaxY = std::get<5>(GetParam());
     192          18 :     const double dfExpectedMaxZ = std::get<6>(GetParam());
     193             : 
     194          18 :     OGRGeometry *poGeom = nullptr;
     195          18 :     ASSERT_EQ(OGRGeometryFactory::createFromWkt(pszInput, nullptr, &poGeom),
     196             :               OGRERR_NONE);
     197          18 :     ASSERT_TRUE(poGeom != nullptr);
     198          36 :     std::vector<GByte> abyWkb(poGeom->WkbSize());
     199          18 :     poGeom->exportToWkb(wkbNDR, abyWkb.data(), wkbVariantIso);
     200          18 :     delete poGeom;
     201          18 :     OGREnvelope3D sEnvelope;
     202          18 :     EXPECT_EQ(OGRWKBGetBoundingBox(abyWkb.data(), abyWkb.size(), sEnvelope),
     203             :               true);
     204          18 :     EXPECT_EQ(sEnvelope.MinX, dfExpectedMinX);
     205          18 :     EXPECT_EQ(sEnvelope.MinY, dfExpectedMinY);
     206          18 :     EXPECT_EQ(sEnvelope.MinZ, dfExpectedMinZ);
     207          18 :     EXPECT_EQ(sEnvelope.MaxX, dfExpectedMaxX);
     208          18 :     EXPECT_EQ(sEnvelope.MaxY, dfExpectedMaxY);
     209          18 :     EXPECT_EQ(sEnvelope.MaxZ, dfExpectedMaxZ);
     210             : }
     211             : 
     212          38 : INSTANTIATE_TEST_SUITE_P(
     213             :     test_ogr_wkb, OGRWKBGetEnvelope3DFixture,
     214             :     ::testing::ValuesIn(OGRWKBGetEnvelope3DFixture::GetTupleValues()),
     215             :     [](const ::testing::TestParamInfo<OGRWKBGetEnvelope3DFixture::ParamType>
     216             :            &l_info) { return std::get<7>(l_info.param); });
     217             : 
     218             : class OGRWKBFixupCounterClockWiseExternalRingFixture
     219             :     : public test_ogr_wkb,
     220             :       public ::testing::WithParamInterface<
     221             :           std::tuple<const char *, const char *, const char *>>
     222             : {
     223             :   public:
     224             :     static std::vector<std::tuple<const char *, const char *, const char *>>
     225           1 :     GetTupleValues()
     226             :     {
     227             :         return {
     228             :             std::make_tuple("MULTIPOLYGON (((0 1,0 0,1 1,0 1),(0.2 0.3,0.2 "
     229             :                             "0.8,0.7 0.8,0.2 0.3)))",
     230             :                             "MULTIPOLYGON (((0 1,0 0,1 1,0 1),(0.2 0.3,0.2 "
     231             :                             "0.8,0.7 0.8,0.2 0.3)))",
     232             :                             "MULTIPOLYGON_CCW"),
     233             :             std::make_tuple("MULTIPOLYGON (((1 1,0 0,0 1,1 1),(0.2 0.3,0.7 "
     234             :                             "0.8,0.2 0.8,0.2 0.3)))",
     235             :                             "MULTIPOLYGON (((1 1,0 1,0 0,1 1),(0.2 0.3,0.2 "
     236             :                             "0.8,0.7 0.8,0.2 0.3)))",
     237             :                             "MULTIPOLYGON_CW"),
     238             :             std::make_tuple(
     239             :                 "MULTIPOLYGON Z (((0 0 10,0 1 10,1 1 10,0 0 10),(0.2 0.3 "
     240             :                 "10,0.7 0.8 10,0.2 0.8 10,0.2 0.3 10)))",
     241             :                 "MULTIPOLYGON Z (((0 0 10,1 1 10,0 1 10,0 0 10),(0.2 0.3 "
     242             :                 "10,0.2 0.8 10,0.7 0.8 10,0.2 0.3 10)))",
     243             :                 "MULTIPOLYGON_CW_3D"),
     244             :             std::make_tuple("MULTIPOLYGON (((0 0,0 0,1 1,1 1,0 1,0 1,0 0)))",
     245             :                             "MULTIPOLYGON (((0 0,0 0,1 1,1 1,0 1,0 1,0 0)))",
     246             :                             "MULTIPOLYGON_CCW_REPEATED_POINTS"),
     247             :             std::make_tuple("MULTIPOLYGON (((0 0,0 0,0 1,0 1,1 1,1 1,0 0)))",
     248             :                             "MULTIPOLYGON (((0 0,1 1,1 1,0 1,0 1,0 0,0 0)))",
     249             :                             "MULTIPOLYGON_CW_REPEATED_POINTS"),
     250             :             std::make_tuple("MULTIPOLYGON EMPTY", "MULTIPOLYGON EMPTY",
     251             :                             "MULTIPOLYGON_EMPTY"),
     252             :             std::make_tuple("POINT (1 2)", "POINT (1 2)", "POINT"),
     253           1 :         };
     254             :     }
     255             : };
     256             : 
     257          15 : TEST_P(OGRWKBFixupCounterClockWiseExternalRingFixture, test)
     258             : {
     259           7 :     const char *pszInput = std::get<0>(GetParam());
     260           7 :     const char *pszExpected = std::get<1>(GetParam());
     261             : 
     262           7 :     OGRGeometry *poGeom = nullptr;
     263           7 :     ASSERT_EQ(OGRGeometryFactory::createFromWkt(pszInput, nullptr, &poGeom),
     264             :               OGRERR_NONE);
     265           7 :     ASSERT_TRUE(poGeom != nullptr);
     266           7 :     std::vector<GByte> abyWkb(poGeom->WkbSize());
     267           7 :     poGeom->exportToWkb(wkbNDR, abyWkb.data());
     268           7 :     OGRWKBFixupCounterClockWiseExternalRing(abyWkb.data(), abyWkb.size());
     269           7 :     delete poGeom;
     270           7 :     poGeom = nullptr;
     271           7 :     OGRGeometryFactory::createFromWkb(abyWkb.data(), nullptr, &poGeom);
     272           7 :     ASSERT_TRUE(poGeom != nullptr);
     273           7 :     char *pszWKT = nullptr;
     274           7 :     poGeom->exportToWkt(&pszWKT, wkbVariantIso);
     275           7 :     EXPECT_STREQ(pszWKT, pszExpected);
     276           7 :     CPLFree(pszWKT);
     277           7 :     delete poGeom;
     278             : }
     279             : 
     280          16 : INSTANTIATE_TEST_SUITE_P(
     281             :     test_ogr_wkb, OGRWKBFixupCounterClockWiseExternalRingFixture,
     282             :     ::testing::ValuesIn(
     283             :         OGRWKBFixupCounterClockWiseExternalRingFixture::GetTupleValues()),
     284             :     [](const ::testing::TestParamInfo<
     285             :         OGRWKBFixupCounterClockWiseExternalRingFixture::ParamType> &l_info)
     286             :     { return std::get<2>(l_info.param); });
     287             : 
     288             : class OGRWKBIntersectsPessimisticFixture
     289             :     : public test_ogr_wkb,
     290             :       public ::testing::WithParamInterface<std::tuple<
     291             :           const char *, double, double, double, double, bool, const char *>>
     292             : {
     293             :   public:
     294             :     static std::vector<std::tuple<const char *, double, double, double, double,
     295             :                                   bool, const char *>>
     296           1 :     GetTupleValues()
     297             :     {
     298             :         return {
     299             :             std::make_tuple("POINT(1 2)", 0.9, 1.9, 1.1, 2.1, true, "POINT_IN"),
     300             :             std::make_tuple("POINT(1 2)", 1.05, 1.9, 1.1, 2.1, false,
     301             :                             "POINT_OUT1"),
     302             :             std::make_tuple("POINT(1 2)", 0.9, 2.05, 1.1, 2.1, false,
     303             :                             "POINT_OUT2"),
     304             :             std::make_tuple("POINT(1 2)", 0.9, 1.9, 0.95, 2.1, false,
     305             :                             "POINT_OUT3"),
     306             :             std::make_tuple("POINT(1 2)", 0.9, 1.9, 1.1, 1.95, false,
     307             :                             "POINT_OUT4"),
     308             :             std::make_tuple("POINT Z (1 2 3)", 0.9, 1.9, 1.1, 2.1, true,
     309             :                             "POINTZ_IN"),
     310             :             std::make_tuple("POINT Z (1 2 3)", 1.05, 1.9, 1.1, 2.1, false,
     311             :                             "POINTZ_OUT"),
     312             :             std::make_tuple("POINT EMPTY", 0.9, 1.9, 1.1, 2.1, false,
     313             :                             "POINT_EMPTY"),
     314             :             std::make_tuple("LINESTRING(1 2, 3 4)", 0.9, 1.9, 1.1, 2.1, true,
     315             :                             "LINESTRING_IN"),
     316             :             std::make_tuple("LINESTRING(1 2, 3 4)", 0.9, 1.9, 0.95, 2.1, false,
     317             :                             "LINESTRING_OUT"),
     318             :             std::make_tuple("LINESTRING EMPTY", 0.9, 1.9, 1.1, 2.1, false,
     319             :                             "LINESTRING_EMPTY"),
     320             :             std::make_tuple("LINESTRING Z (1 2 10, 3 4 10)", 0.9, 1.9, 1.1, 2.1,
     321             :                             true, "LINESTRINGZ_IN"),
     322             :             std::make_tuple("LINESTRING Z (1 2 10, 3 4 10)", 0.9, 1.9, 0.95,
     323             :                             2.1, false, "LINESTRINGZ_OUT"),
     324             :             std::make_tuple("POLYGON((1 2,1 3,10 3,1 2))", 0.9, 1.9, 1.1, 2.1,
     325             :                             true, "POLYGON_IN"),
     326             :             std::make_tuple("POLYGON((1 2,1 3,10 3,1 2))", 0.9, 1.9, 0.95, 2.1,
     327             :                             false, "POLYGON_OUT"),
     328             :             std::make_tuple("POLYGON EMPTY", 0.9, 1.9, 1.1, 2.1, false,
     329             :                             "POLYGON_EMPTY"),
     330             :             std::make_tuple("POLYGON Z ((1 2 -10,1 3 -10,10 3 -10,1 2 -10))",
     331             :                             0.9, 1.9, 1.1, 2.1, true, "POLYGONZ_IN"),
     332             :             std::make_tuple("POLYGON Z ((1 2 -10,1 3 -10,10 3 -10,1 2 -10))",
     333             :                             0.9, 1.9, 0.95, 2.1, false, "POLYGONZ_OUT"),
     334             :             std::make_tuple("MULTIPOINT((1 2))", 0.9, 1.9, 1.1, 2.1, true,
     335             :                             "MULTIPOINT_IN"),
     336             :             std::make_tuple("MULTIPOINT((1 2))", 1.05, 1.9, 1.1, 2.1, false,
     337             :                             "MULTIPOINT_OUT1"),
     338             :             std::make_tuple("MULTIPOINT((1 2))", 0.9, 2.05, 1.1, 2.1, false,
     339             :                             "MULTIPOINT_OUT2"),
     340             :             std::make_tuple("MULTIPOINT((1 2))", 0.9, 1.9, 0.95, 2.1, false,
     341             :                             "MULTIPOINT_OUT3"),
     342             :             std::make_tuple("MULTIPOINT((1 2))", 0.9, 1.9, 1.1, 1.95, false,
     343             :                             "MULTIPOINT_OUT4"),
     344             :             std::make_tuple("MULTIPOINT Z ((1 2 3))", 0.9, 1.9, 1.1, 2.1, true,
     345             :                             "MULTIPOINTZ_IN"),
     346             :             std::make_tuple("MULTIPOINT Z ((1 2 3))", 1.05, 1.9, 1.1, 2.1,
     347             :                             false, "MULTIPOINTZ_OUT"),
     348             :             std::make_tuple("MULTIPOINT EMPTY", 0.9, 1.9, 1.1, 2.1, false,
     349             :                             "MULTIPOINT_EMPTY"),
     350             :             std::make_tuple("MULTILINESTRING((1 2, 3 4))", 0.9, 1.9, 1.1, 2.1,
     351             :                             true, "MULTILINESTRING_IN"),
     352             :             std::make_tuple("MULTILINESTRING((1 2, 3 4))", 0.9, 1.9, 0.95, 2.1,
     353             :                             false, "MULTILINESTRING_OUT"),
     354             :             std::make_tuple("MULTILINESTRING EMPTY", 0.9, 1.9, 1.1, 2.1, false,
     355             :                             "MULTILINESTRING_EMPTY"),
     356             :             std::make_tuple("MULTILINESTRING Z ((1 2 10, 3 4 10))", 0.9, 1.9,
     357             :                             1.1, 2.1, true, "MULTILINESTRINGZ_IN"),
     358             :             std::make_tuple("MULTILINESTRING Z ((1 2 10, 3 4 10))", 0.9, 1.9,
     359             :                             0.95, 2.1, false, "MULTILINESTRINGZ_OUT"),
     360             :             std::make_tuple("MULTIPOLYGON(((1 2,1 3,10 3,1 2)))", 0.9, 1.9, 1.1,
     361             :                             2.1, true, "MULTIPOLYGON_IN"),
     362             :             std::make_tuple("MULTIPOLYGON(((1 2,1 3,10 3,1 2)))", 0.9, 1.9,
     363             :                             0.95, 2.1, false, "MULTIPOLYGON_OUT"),
     364             :             std::make_tuple("MULTIPOLYGON EMPTY", 0.9, 1.9, 1.1, 2.1, false,
     365             :                             "MULTIPOLYGON_EMPTY"),
     366             :             std::make_tuple(
     367             :                 "MULTIPOLYGON Z (((1 2 -10,1 3 -10,10 3 -10,1 2 -10)))", 0.9,
     368             :                 1.9, 1.1, 2.1, true, "MULTIPOLYGONZ_IN"),
     369             :             std::make_tuple(
     370             :                 "MULTIPOLYGON Z (((1 2 -10,1 3 -10,10 3 -10,1 2 -10)))", 0.9,
     371             :                 1.9, 0.95, 2.1, false, "MULTIPOLYGONZ_OUT"),
     372             :             std::make_tuple("GEOMETRYCOLLECTION(POINT(1 2))", 0.9, 1.9, 1.1,
     373             :                             2.1, true, "GEOMETRYCOLLECTION_POINT_IN"),
     374             :             std::make_tuple("CIRCULARSTRING(0 10,1 11,2 10)", -0.1, 9.9, 0.1,
     375             :                             10.1, true, "CIRCULARSTRING_IN"),
     376             :             std::make_tuple("CIRCULARSTRING(0 10,1 11,2 10)", -0.1, 9.9, -0.05,
     377             :                             10.1, false, "CIRCULARSTRING_OUT"),
     378             :             std::make_tuple("CIRCULARSTRING EMPTY", -0.1, 9.9, 0.1, 10.1, false,
     379             :                             "CIRCULARSTRING_EMPTY"),
     380             :             std::make_tuple("TRIANGLE((1 2,1 3,10 3,1 2))", 0.9, 1.9, 1.1, 2.1,
     381             :                             true, "TRIANGLE_IN"),
     382             :             std::make_tuple("TRIANGLE((1 2,1 3,10 3,1 2))", 0.9, 1.9, 0.95, 2.1,
     383             :                             false, "TRIANGLE_OUT"),
     384             :             std::make_tuple("TRIANGLE EMPTY", 0.9, 1.9, 1.1, 2.1, false,
     385             :                             "TRIANGLE_EMPTY"),
     386             :             std::make_tuple("TRIANGLE Z ((1 2 -10,1 3 -10,10 3 -10,1 2 -10))",
     387             :                             0.9, 1.9, 1.1, 2.1, true, "TRIANGLEZ_IN"),
     388             :             std::make_tuple("TRIANGLE Z ((1 2 -10,1 3 -10,10 3 -10,1 2 -10))",
     389             :                             0.9, 1.9, 0.95, 2.1, false, "TRIANGLEZ_OUT"),
     390             :             std::make_tuple("COMPOUNDCURVE((1 2, 3 4))", 0.9, 1.9, 1.1, 2.1,
     391             :                             true, "COMPOUNDCURVE_IN"),
     392             :             std::make_tuple("COMPOUNDCURVE((1 2, 3 4))", 0.9, 1.9, 0.95, 2.1,
     393             :                             false, "COMPOUNDCURVE_OUT"),
     394             :             std::make_tuple("COMPOUNDCURVE EMPTY", 0.9, 1.9, 1.1, 2.1, false,
     395             :                             "COMPOUNDCURVE_EMPTY"),
     396             :             std::make_tuple("COMPOUNDCURVE Z ((1 2 10, 3 4 10))", 0.9, 1.9, 1.1,
     397             :                             2.1, true, "COMPOUNDCURVEZ_IN"),
     398             :             std::make_tuple("COMPOUNDCURVE Z ((1 2 10, 3 4 10))", 0.9, 1.9,
     399             :                             0.95, 2.1, false, "COMPOUNDCURVEZ_OUT"),
     400             :             std::make_tuple("CURVEPOLYGON((1 2,1 3,10 3,1 2))", 0.9, 1.9, 1.1,
     401             :                             2.1, true, "CURVEPOLYGON_IN"),
     402             :             std::make_tuple("CURVEPOLYGON((1 2,1 3,10 3,1 2))", 0.9, 1.9, 0.95,
     403             :                             2.1, false, "CURVEPOLYGON_OUT"),
     404             :             std::make_tuple("CURVEPOLYGON EMPTY", 0.9, 1.9, 1.1, 2.1, false,
     405             :                             "CURVEPOLYGON_EMPTY"),
     406             :             std::make_tuple(
     407             :                 "CURVEPOLYGON Z ((1 2 -10,1 3 -10,10 3 -10,1 2 -10))", 0.9, 1.9,
     408             :                 1.1, 2.1, true, "CURVEPOLYGONZ_IN"),
     409             :             std::make_tuple(
     410             :                 "CURVEPOLYGON Z ((1 2 -10,1 3 -10,10 3 -10,1 2 -10))", 0.9, 1.9,
     411             :                 0.95, 2.1, false, "CURVEPOLYGONZ_OUT"),
     412             :             std::make_tuple("MULTICURVE((1 2, 3 4))", 0.9, 1.9, 1.1, 2.1, true,
     413             :                             "MULTICURVE_IN"),
     414             :             std::make_tuple("MULTICURVE((1 2, 3 4))", 0.9, 1.9, 0.95, 2.1,
     415             :                             false, "MULTICURVE_OUT"),
     416             :             std::make_tuple("MULTICURVE EMPTY", 0.9, 1.9, 1.1, 2.1, false,
     417             :                             "MULTICURVE_EMPTY"),
     418             :             std::make_tuple("MULTICURVE Z ((1 2 10, 3 4 10))", 0.9, 1.9, 1.1,
     419             :                             2.1, true, "MULTICURVEZ_IN"),
     420             :             std::make_tuple("MULTICURVE Z ((1 2 10, 3 4 10))", 0.9, 1.9, 0.95,
     421             :                             2.1, false, "MULTICURVEZ_OUT"),
     422             :             std::make_tuple("MULTISURFACE(((1 2,1 3,10 3,1 2)))", 0.9, 1.9, 1.1,
     423             :                             2.1, true, "MULTISURFACE_IN"),
     424             :             std::make_tuple("MULTISURFACE(((1 2,1 3,10 3,1 2)))", 0.9, 1.9,
     425             :                             0.95, 2.1, false, "MULTISURFACE_OUT"),
     426             :             std::make_tuple("MULTISURFACE EMPTY", 0.9, 1.9, 1.1, 2.1, false,
     427             :                             "MULTISURFACE_EMPTY"),
     428             :             std::make_tuple(
     429             :                 "MULTISURFACE Z (((1 2 -10,1 3 -10,10 3 -10,1 2 -10)))", 0.9,
     430             :                 1.9, 1.1, 2.1, true, "MULTISURFACEZ_IN"),
     431             :             std::make_tuple(
     432             :                 "MULTISURFACE Z (((1 2 -10,1 3 -10,10 3 -10,1 2 -10)))", 0.9,
     433             :                 1.9, 0.95, 2.1, false, "MULTISURFACEZ_OUT"),
     434             :             std::make_tuple("POLYHEDRALSURFACE(((1 2,1 3,10 3,1 2)))", 0.9, 1.9,
     435             :                             1.1, 2.1, true, "POLYHEDRALSURFACE_IN"),
     436             :             std::make_tuple("POLYHEDRALSURFACE(((1 2,1 3,10 3,1 2)))", 0.9, 1.9,
     437             :                             0.95, 2.1, false, "POLYHEDRALSURFACE_OUT"),
     438             :             std::make_tuple("POLYHEDRALSURFACE EMPTY", 0.9, 1.9, 1.1, 2.1,
     439             :                             false, "POLYHEDRALSURFACE_EMPTY"),
     440             :             std::make_tuple(
     441             :                 "POLYHEDRALSURFACE Z (((1 2 -10,1 3 -10,10 3 -10,1 2 -10)))",
     442             :                 0.9, 1.9, 1.1, 2.1, true, "POLYHEDRALSURFACEZ_IN"),
     443             :             std::make_tuple(
     444             :                 "POLYHEDRALSURFACE Z (((1 2 -10,1 3 -10,10 3 -10,1 2 -10)))",
     445             :                 0.9, 1.9, 0.95, 2.1, false, "POLYHEDRALSURFACEZ_OUT"),
     446             :             std::make_tuple("TIN(((1 2,1 3,10 3,1 2)))", 0.9, 1.9, 1.1, 2.1,
     447             :                             true, "TIN_IN"),
     448             :             std::make_tuple("TIN(((1 2,1 3,10 3,1 2)))", 0.9, 1.9, 0.95, 2.1,
     449             :                             false, "TIN_OUT"),
     450             :             std::make_tuple("TIN EMPTY", 0.9, 1.9, 1.1, 2.1, false,
     451             :                             "TIN_EMPTY"),
     452             :             std::make_tuple("TIN Z (((1 2 -10,1 3 -10,10 3 -10,1 2 -10)))", 0.9,
     453             :                             1.9, 1.1, 2.1, true, "TINZ_IN"),
     454             :             std::make_tuple("TIN Z (((1 2 -10,1 3 -10,10 3 -10,1 2 -10)))", 0.9,
     455             :                             1.9, 0.95, 2.1, false, "TINZ_OUT"),
     456           1 :         };
     457             :     }
     458             : };
     459             : 
     460         151 : TEST_P(OGRWKBIntersectsPessimisticFixture, test)
     461             : {
     462          75 :     const char *pszInput = std::get<0>(GetParam());
     463          75 :     const double dfMinX = std::get<1>(GetParam());
     464          75 :     const double dfMinY = std::get<2>(GetParam());
     465          75 :     const double dfMaxX = std::get<3>(GetParam());
     466          75 :     const double dfMaxY = std::get<4>(GetParam());
     467          75 :     const bool bIntersects = std::get<5>(GetParam());
     468             : 
     469          75 :     OGRGeometry *poGeom = nullptr;
     470          75 :     EXPECT_EQ(OGRGeometryFactory::createFromWkt(pszInput, nullptr, &poGeom),
     471             :               OGRERR_NONE);
     472          75 :     ASSERT_TRUE(poGeom != nullptr);
     473         150 :     std::vector<GByte> abyWkb(poGeom->WkbSize());
     474          75 :     poGeom->exportToWkb(wkbNDR, abyWkb.data(), wkbVariantIso);
     475          75 :     delete poGeom;
     476          75 :     OGREnvelope sEnvelope;
     477          75 :     sEnvelope.MinX = dfMinX;
     478          75 :     sEnvelope.MinY = dfMinY;
     479          75 :     sEnvelope.MaxX = dfMaxX;
     480          75 :     sEnvelope.MaxY = dfMaxY;
     481          75 :     EXPECT_EQ(
     482             :         OGRWKBIntersectsPessimistic(abyWkb.data(), abyWkb.size(), sEnvelope),
     483             :         bIntersects);
     484             : 
     485          75 :     if (abyWkb.size() > 9)
     486             :     {
     487          62 :         EXPECT_EQ(OGRWKBIntersectsPessimistic(abyWkb.data(), 9, sEnvelope),
     488             :                   false);
     489             : 
     490          62 :         if (!STARTS_WITH(pszInput, "POINT"))
     491             :         {
     492             :             // Corrupt number of sub-geometries
     493          54 :             abyWkb[5] = 0xff;
     494          54 :             abyWkb[6] = 0xff;
     495          54 :             abyWkb[7] = 0xff;
     496          54 :             abyWkb[8] = 0xff;
     497          54 :             EXPECT_EQ(OGRWKBIntersectsPessimistic(abyWkb.data(), abyWkb.size(),
     498             :                                                   sEnvelope),
     499             :                       false);
     500             :         }
     501             :     }
     502             : }
     503             : 
     504         152 : INSTANTIATE_TEST_SUITE_P(
     505             :     test_ogr_wkb, OGRWKBIntersectsPessimisticFixture,
     506             :     ::testing::ValuesIn(OGRWKBIntersectsPessimisticFixture::GetTupleValues()),
     507             :     [](const ::testing::TestParamInfo<
     508             :         OGRWKBIntersectsPessimisticFixture::ParamType> &l_info)
     509             :     { return std::get<6>(l_info.param); });
     510             : 
     511             : class OGRWKBTransformFixture
     512             :     : public test_ogr_wkb,
     513             :       public ::testing::WithParamInterface<
     514             :           std::tuple<const char *, OGRwkbByteOrder, const char *, const char *>>
     515             : {
     516             :   public:
     517             :     static std::vector<
     518             :         std::tuple<const char *, OGRwkbByteOrder, const char *, const char *>>
     519           1 :     GetTupleValues()
     520             :     {
     521             :         return {
     522             :             std::make_tuple("POINT EMPTY", wkbNDR, "POINT EMPTY",
     523             :                             "POINT_EMPTY_NDR"),
     524             :             std::make_tuple("POINT EMPTY", wkbXDR, "POINT EMPTY",
     525             :                             "POINT_EMPTY_XDR"),
     526             :             std::make_tuple("POINT (1 2)", wkbNDR, "POINT (2 4)", "POINT_NDR"),
     527             :             std::make_tuple("POINT (1 2)", wkbXDR, "POINT (2 4)", "POINT_XDR"),
     528             :             std::make_tuple("POINT Z EMPTY", wkbNDR, "POINT Z EMPTY",
     529             :                             "POINT_Z_EMPTY_NDR"),
     530             :             std::make_tuple("POINT Z EMPTY", wkbXDR, "POINT Z EMPTY",
     531             :                             "POINT_Z_EMPTY_XDR"),
     532             :             std::make_tuple("POINT Z (1 2 3)", wkbNDR, "POINT Z (2 4 6)",
     533             :                             "POINT_Z_NDR"),
     534             :             std::make_tuple("POINT Z (1 2 3)", wkbXDR, "POINT Z (2 4 6)",
     535             :                             "POINT_Z_XDR"),
     536             :             std::make_tuple("POINT M EMPTY", wkbNDR, "POINT M EMPTY",
     537             :                             "POINT_M_EMPTY_NDR"),
     538             :             std::make_tuple("POINT M EMPTY", wkbXDR, "POINT M EMPTY",
     539             :                             "POINT_M_EMPTY_XDR"),
     540             :             std::make_tuple("POINT M (1 2 -10)", wkbNDR, "POINT M (2 4 -10)",
     541             :                             "POINT_M_NDR"),
     542             :             std::make_tuple("POINT M (1 2 -10)", wkbXDR, "POINT M (2 4 -10)",
     543             :                             "POINT_M_XDR"),
     544             :             std::make_tuple("POINT ZM EMPTY", wkbNDR, "POINT ZM EMPTY",
     545             :                             "POINT_ZM_EMPTY_NDR"),
     546             :             std::make_tuple("POINT ZM EMPTY", wkbXDR, "POINT ZM EMPTY",
     547             :                             "POINT_ZM_EMPTY_XDR"),
     548             :             std::make_tuple("POINT ZM (1 2 3 10)", wkbNDR,
     549             :                             "POINT ZM (2 4 6 10)", "POINT_ZM_NDR"),
     550             :             std::make_tuple("POINT ZM (1 2 3 10)", wkbXDR,
     551             :                             "POINT ZM (2 4 6 10)", "POINT_ZM_XDR"),
     552             : 
     553             :             std::make_tuple("LINESTRING EMPTY", wkbNDR, "LINESTRING EMPTY",
     554             :                             "LINESTRING_EMPTY"),
     555             :             std::make_tuple("LINESTRING (1 2,11 12)", wkbNDR,
     556             :                             "LINESTRING (2 4,12 14)", "LINESTRING_NDR"),
     557             :             std::make_tuple("LINESTRING (1 2,11 12)", wkbXDR,
     558             :                             "LINESTRING (2 4,12 14)", "LINESTRING_XDR"),
     559             :             std::make_tuple("LINESTRING Z EMPTY", wkbNDR, "LINESTRING Z EMPTY",
     560             :                             "LINESTRING_Z_EMPTY"),
     561             :             std::make_tuple("LINESTRING Z (1 2 3,11 12 13)", wkbNDR,
     562             :                             "LINESTRING Z (2 4 6,12 14 16)",
     563             :                             "LINESTRING_Z_NDR"),
     564             :             std::make_tuple("LINESTRING Z (1 2 3,11 12 13)", wkbXDR,
     565             :                             "LINESTRING Z (2 4 6,12 14 16)",
     566             :                             "LINESTRING_Z_XDR"),
     567             :             std::make_tuple("LINESTRING M EMPTY", wkbNDR, "LINESTRING M EMPTY",
     568             :                             "LINESTRING_M_EMPTY"),
     569             :             std::make_tuple("LINESTRING M (1 2 -10,11 12 -20)", wkbNDR,
     570             :                             "LINESTRING M (2 4 -10,12 14 -20)",
     571             :                             "LINESTRING_M_NDR"),
     572             :             std::make_tuple("LINESTRING M (1 2 -10,11 12 -20)", wkbXDR,
     573             :                             "LINESTRING M (2 4 -10,12 14 -20)",
     574             :                             "LINESTRING_M_XDR"),
     575             :             std::make_tuple("LINESTRING ZM EMPTY", wkbNDR,
     576             :                             "LINESTRING ZM EMPTY", "LINESTRING_ZM_EMPTY"),
     577             :             std::make_tuple("LINESTRING ZM (1 2 3 -10,11 12 13 -20)", wkbNDR,
     578             :                             "LINESTRING ZM (2 4 6 -10,12 14 16 -20)",
     579             :                             "LINESTRING_ZM_NDR"),
     580             :             std::make_tuple("LINESTRING ZM (1 2 3 -10,11 12 13 -20)", wkbXDR,
     581             :                             "LINESTRING ZM (2 4 6 -10,12 14 16 -20)",
     582             :                             "LINESTRING_ZM_XDR"),
     583             : 
     584             :             // I know the polygon is invalid, but this is enough for our purposes
     585             :             std::make_tuple("POLYGON EMPTY", wkbNDR, "POLYGON EMPTY",
     586             :                             "POLYGON_EMPTY"),
     587             :             std::make_tuple("POLYGON ((1 2,11 12))", wkbNDR,
     588             :                             "POLYGON ((2 4,12 14))", "POLYGON_NDR"),
     589             :             std::make_tuple("POLYGON ((1 2,11 12))", wkbXDR,
     590             :                             "POLYGON ((2 4,12 14))", "POLYGON_XDR"),
     591             :             std::make_tuple("POLYGON ((1 2,11 12),(21 22,31 32))", wkbNDR,
     592             :                             "POLYGON ((2 4,12 14),(22 24,32 34))",
     593             :                             "POLYGON_TWO_RINGS"),
     594             :             std::make_tuple("POLYGON Z EMPTY", wkbNDR, "POLYGON Z EMPTY",
     595             :                             "POLYGON_Z_EMPTY"),
     596             :             std::make_tuple("POLYGON Z ((1 2 3,11 12 13))", wkbNDR,
     597             :                             "POLYGON Z ((2 4 6,12 14 16))", "POLYGON_Z_NDR"),
     598             :             std::make_tuple("POLYGON Z ((1 2 3,11 12 13))", wkbXDR,
     599             :                             "POLYGON Z ((2 4 6,12 14 16))", "POLYGON_Z_XDR"),
     600             :             std::make_tuple("POLYGON M EMPTY", wkbNDR, "POLYGON M EMPTY",
     601             :                             "POLYGON_M_EMPTY"),
     602             :             std::make_tuple("POLYGON M ((1 2 -10,11 12 -20))", wkbNDR,
     603             :                             "POLYGON M ((2 4 -10,12 14 -20))", "POLYGON_M_NDR"),
     604             :             std::make_tuple("POLYGON M ((1 2 -10,11 12 -20))", wkbXDR,
     605             :                             "POLYGON M ((2 4 -10,12 14 -20))", "POLYGON_M_XDR"),
     606             :             std::make_tuple("POLYGON ZM EMPTY", wkbNDR, "POLYGON ZM EMPTY",
     607             :                             "POLYGON_ZM_EMPTY"),
     608             :             std::make_tuple("POLYGON ZM ((1 2 3 -10,11 12 13 -20))", wkbNDR,
     609             :                             "POLYGON ZM ((2 4 6 -10,12 14 16 -20))",
     610             :                             "POLYGON_ZM_NDR"),
     611             :             std::make_tuple("POLYGON ZM ((1 2 3 -10,11 12 13 -20))", wkbXDR,
     612             :                             "POLYGON ZM ((2 4 6 -10,12 14 16 -20))",
     613             :                             "POLYGON_ZM_XDR"),
     614             : 
     615             :             std::make_tuple("MULTIPOINT EMPTY", wkbNDR, "MULTIPOINT EMPTY",
     616             :                             "MULTIPOINT_EMPTY_NDR"),
     617             :             std::make_tuple("MULTIPOINT ((1 2),(11 12))", wkbNDR,
     618             :                             "MULTIPOINT ((2 4),(12 14))", "MULTIPOINT_NDR"),
     619             :             std::make_tuple("MULTIPOINT Z ((1 2 3),(11 12 13))", wkbXDR,
     620             :                             "MULTIPOINT Z ((2 4 6),(12 14 16))",
     621             :                             "MULTIPOINT_Z_XDR"),
     622             : 
     623             :             std::make_tuple("MULTILINESTRING ((1 2,11 12))", wkbNDR,
     624             :                             "MULTILINESTRING ((2 4,12 14))",
     625             :                             "MULTILINESTRING_NDR"),
     626             : 
     627             :             std::make_tuple("MULTIPOLYGON (((1 2,11 12)))", wkbNDR,
     628             :                             "MULTIPOLYGON (((2 4,12 14)))", "MULTIPOLYGON_NDR"),
     629             : 
     630             :             std::make_tuple("GEOMETRYCOLLECTION (POLYGON ((1 2,11 12)))",
     631             :                             wkbNDR,
     632             :                             "GEOMETRYCOLLECTION (POLYGON ((2 4,12 14)))",
     633             :                             "GEOMETRYCOLLECTION_NDR"),
     634             : 
     635             :             std::make_tuple("CIRCULARSTRING (1 2,11 12,21 22)", wkbNDR,
     636             :                             "CIRCULARSTRING (2 4,12 14,22 24)",
     637             :                             "CIRCULARSTRING_NDR"),
     638             : 
     639             :             std::make_tuple("COMPOUNDCURVE ((1 2,11 12))", wkbNDR,
     640             :                             "COMPOUNDCURVE ((2 4,12 14))", "COMPOUNDCURVE_NDR"),
     641             : 
     642             :             std::make_tuple("CURVEPOLYGON ((1 2,11 12,21 22,1 2))", wkbNDR,
     643             :                             "CURVEPOLYGON ((2 4,12 14,22 24,2 4))",
     644             :                             "CURVEPOLYGON_NDR"),
     645             : 
     646             :             std::make_tuple("MULTICURVE ((1 2,11 12))", wkbNDR,
     647             :                             "MULTICURVE ((2 4,12 14))", "MULTICURVE_NDR"),
     648             : 
     649             :             std::make_tuple("MULTISURFACE (((1 2,11 12)))", wkbNDR,
     650             :                             "MULTISURFACE (((2 4,12 14)))", "MULTISURFACE_NDR"),
     651             : 
     652             :             std::make_tuple("TRIANGLE ((1 2,11 12,21 22,1 2))", wkbNDR,
     653             :                             "TRIANGLE ((2 4,12 14,22 24,2 4))", "TRIANGLE_NDR"),
     654             : 
     655             :             std::make_tuple("POLYHEDRALSURFACE (((1 2,11 12,21 22,1 2)))",
     656             :                             wkbNDR,
     657             :                             "POLYHEDRALSURFACE (((2 4,12 14,22 24,2 4)))",
     658             :                             "POLYHEDRALSURFACE_NDR"),
     659             : 
     660             :             std::make_tuple("TIN (((1 2,11 12,21 22,1 2)))", wkbNDR,
     661             :                             "TIN (((2 4,12 14,22 24,2 4)))", "TIN_NDR"),
     662           1 :         };
     663             :     }
     664             : };
     665             : 
     666             : struct MyCT final : public OGRCoordinateTransformation
     667             : {
     668             :     const bool m_bSuccess;
     669             : 
     670         112 :     explicit MyCT(bool bSuccess = true) : m_bSuccess(bSuccess)
     671             :     {
     672         112 :     }
     673             : 
     674          55 :     const OGRSpatialReference *GetSourceCS() const override
     675             :     {
     676          55 :         return nullptr;
     677             :     }
     678             : 
     679          55 :     const OGRSpatialReference *GetTargetCS() const override
     680             :     {
     681          55 :         return nullptr;
     682             :     }
     683             : 
     684        3976 :     int Transform(size_t nCount, double *x, double *y, double *z, double *,
     685             :                   int *pabSuccess) override
     686             :     {
     687        7952 :         for (size_t i = 0; i < nCount; ++i)
     688             :         {
     689        3976 :             x[i] += 1;
     690        3976 :             y[i] += 2;
     691        3976 :             if (z)
     692        3976 :                 z[i] += 3;
     693        3976 :             if (pabSuccess)
     694        3976 :                 pabSuccess[i] = m_bSuccess;
     695             :         }
     696        3976 :         return true;
     697             :     }
     698             : 
     699          55 :     OGRCoordinateTransformation *Clone() const override
     700             :     {
     701          55 :         return new MyCT();
     702             :     }
     703             : 
     704          55 :     OGRCoordinateTransformation *GetInverse() const override
     705             :     {
     706          55 :         return nullptr;
     707             :     }  // unused
     708             : };
     709             : 
     710         111 : TEST_P(OGRWKBTransformFixture, test)
     711             : {
     712          55 :     const char *pszInput = std::get<0>(GetParam());
     713          55 :     OGRwkbByteOrder eByteOrder = std::get<1>(GetParam());
     714          55 :     const char *pszOutput = std::get<2>(GetParam());
     715             : 
     716          55 :     MyCT oCT;
     717          55 :     oCT.GetSourceCS();        // just for code coverage purpose
     718          55 :     oCT.GetTargetCS();        // just for code coverage purpose
     719          55 :     delete oCT.Clone();       // just for code coverage purpose
     720          55 :     delete oCT.GetInverse();  // just for code coverage purpose
     721             : 
     722          55 :     OGRGeometry *poGeom = nullptr;
     723          55 :     EXPECT_EQ(OGRGeometryFactory::createFromWkt(pszInput, nullptr, &poGeom),
     724             :               OGRERR_NONE);
     725          55 :     ASSERT_TRUE(poGeom != nullptr);
     726          55 :     std::vector<GByte> abyWkb(poGeom->WkbSize());
     727          55 :     poGeom->exportToWkb(eByteOrder, abyWkb.data(), wkbVariantIso);
     728          55 :     delete poGeom;
     729             : 
     730             :     OGRWKBTransformCache oCache;
     731          55 :     OGREnvelope3D sEnv;
     732          55 :     EXPECT_TRUE(
     733             :         OGRWKBTransform(abyWkb.data(), abyWkb.size(), &oCT, oCache, sEnv));
     734          55 :     const auto abyWkbOri = abyWkb;
     735             : 
     736          55 :     poGeom = nullptr;
     737          55 :     OGRGeometryFactory::createFromWkb(abyWkb.data(), nullptr, &poGeom,
     738             :                                       abyWkb.size());
     739          55 :     ASSERT_TRUE(poGeom != nullptr);
     740          55 :     char *pszWKT = nullptr;
     741          55 :     poGeom->exportToWkt(&pszWKT, wkbVariantIso);
     742          55 :     delete poGeom;
     743          55 :     EXPECT_STREQ(pszWKT, pszOutput);
     744          55 :     CPLFree(pszWKT);
     745             : 
     746             :     {
     747         110 :         CPLErrorHandlerPusher oErrorHandler(CPLQuietErrorHandler);
     748             : 
     749             :         // Truncated geometry
     750        2443 :         for (size_t i = 0; i < abyWkb.size(); ++i)
     751             :         {
     752        2388 :             abyWkb = abyWkbOri;
     753        2388 :             EXPECT_FALSE(OGRWKBTransform(abyWkb.data(), i, &oCT, oCache, sEnv));
     754             :         }
     755             : 
     756             :         // Check altering all bytes
     757        2443 :         for (size_t i = 0; i < abyWkb.size(); ++i)
     758             :         {
     759        2388 :             abyWkb = abyWkbOri;
     760        2388 :             abyWkb[i] = 0xff;
     761        2388 :             CPL_IGNORE_RET_VAL(OGRWKBTransform(abyWkb.data(), abyWkb.size(),
     762             :                                                &oCT, oCache, sEnv));
     763             :         }
     764             : 
     765          55 :         if (abyWkb.size() > 9)
     766             :         {
     767          46 :             abyWkb = abyWkbOri;
     768          46 :             if (!STARTS_WITH(pszInput, "POINT"))
     769             :             {
     770             :                 // Corrupt number of sub-geometries
     771          30 :                 abyWkb[5] = 0xff;
     772          30 :                 abyWkb[6] = 0xff;
     773          30 :                 abyWkb[7] = 0xff;
     774          30 :                 abyWkb[8] = 0xff;
     775          30 :                 EXPECT_FALSE(OGRWKBTransform(abyWkb.data(), abyWkb.size(), &oCT,
     776             :                                              oCache, sEnv));
     777             :             }
     778             :         }
     779             :     }
     780             : }
     781             : 
     782         112 : INSTANTIATE_TEST_SUITE_P(
     783             :     test_ogr_wkb, OGRWKBTransformFixture,
     784             :     ::testing::ValuesIn(OGRWKBTransformFixture::GetTupleValues()),
     785             :     [](const ::testing::TestParamInfo<OGRWKBTransformFixture::ParamType>
     786             :            &l_info) { return std::get<3>(l_info.param); });
     787             : 
     788           4 : TEST_F(test_ogr_wkb, OGRWKBTransformFixture_rec_collection)
     789             : {
     790           2 :     std::vector<GByte> abyWkb;
     791           1 :     constexpr int BEYOND_ALLOWED_RECURSION_LEVEL = 128;
     792         129 :     for (int i = 0; i < BEYOND_ALLOWED_RECURSION_LEVEL; ++i)
     793             :     {
     794         128 :         abyWkb.push_back(wkbNDR);
     795         128 :         abyWkb.push_back(wkbGeometryCollection);
     796         128 :         abyWkb.push_back(0);
     797         128 :         abyWkb.push_back(0);
     798         128 :         abyWkb.push_back(0);
     799         128 :         abyWkb.push_back(1);
     800         128 :         abyWkb.push_back(0);
     801         128 :         abyWkb.push_back(0);
     802         128 :         abyWkb.push_back(0);
     803             :     }
     804             :     {
     805           1 :         abyWkb.push_back(wkbNDR);
     806           1 :         abyWkb.push_back(wkbGeometryCollection);
     807           1 :         abyWkb.push_back(0);
     808           1 :         abyWkb.push_back(0);
     809           1 :         abyWkb.push_back(0);
     810           1 :         abyWkb.push_back(0);
     811           1 :         abyWkb.push_back(0);
     812           1 :         abyWkb.push_back(0);
     813           1 :         abyWkb.push_back(0);
     814             :     }
     815             : 
     816           2 :     MyCT oCT;
     817             :     OGRWKBTransformCache oCache;
     818           1 :     OGREnvelope3D sEnv;
     819           1 :     EXPECT_FALSE(
     820             :         OGRWKBTransform(abyWkb.data(), abyWkb.size(), &oCT, oCache, sEnv));
     821           1 : }
     822             : 
     823           4 : TEST_F(test_ogr_wkb, OGRWKBTransformFixture_ct_failure)
     824             : {
     825           2 :     MyCT oCT(/* bSuccess = */ false);
     826             :     OGRWKBTransformCache oCache;
     827           1 :     OGREnvelope3D sEnv;
     828             :     {
     829           2 :         OGRPoint p(1, 2);
     830           2 :         std::vector<GByte> abyWkb(p.WkbSize());
     831           1 :         static_cast<OGRGeometry &>(p).exportToWkb(wkbNDR, abyWkb.data(),
     832             :                                                   wkbVariantIso);
     833             : 
     834           1 :         EXPECT_FALSE(
     835             :             OGRWKBTransform(abyWkb.data(), abyWkb.size(), &oCT, oCache, sEnv));
     836             :     }
     837             :     {
     838           2 :         OGRLineString ls;
     839           1 :         ls.addPoint(1, 2);
     840           2 :         std::vector<GByte> abyWkb(ls.WkbSize());
     841           1 :         static_cast<OGRGeometry &>(ls).exportToWkb(wkbNDR, abyWkb.data(),
     842             :                                                    wkbVariantIso);
     843             : 
     844           1 :         EXPECT_FALSE(
     845             :             OGRWKBTransform(abyWkb.data(), abyWkb.size(), &oCT, oCache, sEnv));
     846             :     }
     847             :     {
     848           2 :         OGRPolygon p;
     849           2 :         auto poLR = std::make_unique<OGRLinearRing>();
     850           1 :         poLR->addPoint(1, 2);
     851           1 :         p.addRing(std::move(poLR));
     852           2 :         std::vector<GByte> abyWkb(p.WkbSize());
     853           1 :         static_cast<OGRGeometry &>(p).exportToWkb(wkbNDR, abyWkb.data(),
     854             :                                                   wkbVariantIso);
     855             : 
     856           1 :         EXPECT_FALSE(
     857             :             OGRWKBTransform(abyWkb.data(), abyWkb.size(), &oCT, oCache, sEnv));
     858             :     }
     859           1 : }
     860             : 
     861             : }  // namespace

Generated by: LCOV version 1.14