LCOV - code coverage report
Current view: top level - autotest/cpp - testvirtualmem.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 95 98 96.9 %
Date: 2024-05-14 13:00:50 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  * $Id$
       3             :  *
       4             :  * Project:  GDAL algorithms
       5             :  * Purpose:  Test Delaunay triangulation
       6             :  * Author:   Even Rouault, even.rouault at spatialys.com
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2014, Even Rouault <even.rouault at spatialys.com>
      10             :  *
      11             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "cpl_multiproc.h"
      31             : #include "cpl_string.h"
      32             : #include "cpl_virtualmem.h"
      33             : #include "gdal_alg.h"
      34             : #include "gdal.h"
      35             : 
      36             : #include "gtest_include.h"
      37             : 
      38             : #include "test_data.h"
      39             : 
      40             : namespace
      41             : {
      42             : 
      43             : // ---------------------------------------------------------------------------
      44             : 
      45             : #ifdef notdef
      46             : static void test_huge_mapping_cbk(CPLVirtualMem *ctxt, size_t nOffset,
      47             :                                   void *pPageToFill, size_t nPageSize,
      48             :                                   void *pUserData)
      49             : {
      50             :     /*fprintfstderr("requesting page %lu (nPageSize=%d), nLRUSize=%d\n",
      51             :             (unsigned long)(nOffset / nPageSize),
      52             :             (int)nPageSize,
      53             :             ctxt->nLRUSize);*/
      54             :     memset(pPageToFill, 0x7F, nPageSize);
      55             : }
      56             : 
      57             : static void test_huge_mapping()
      58             : {
      59             :     CPLVirtualMem *ctxt;
      60             :     char *addr;
      61             :     int i;
      62             : 
      63             :     ctxt = CPLVirtualMemNew(
      64             :         (size_t)10000 * 1024 * 1024, (size_t)2000 * 1024 * 1024, 0, TRUE,
      65             :         VIRTUALMEM_READONLY, test_huge_mapping_cbk, NULL, NULL, NULL);
      66             :     ASSERT_TRUE(ctxt != nullptr);
      67             :     addr = (char *)CPLVirtualMemGetAddr(ctxt);
      68             :     for (i = 0; i < 50 * 1000; i++)
      69             :     {
      70             :         unsigned int seedp;
      71             :         size_t idx = (size_t)rand_r(&seedp) * 3000 * 1024 / RAND_MAX * 1024;
      72             :         char val = addr[idx];
      73             :         /*printf("i=%d, val[%ld] = %d\n", i, (long int)idx, val);*/
      74             :         ASSERT_EQ(val, 0x7F);
      75             :     }
      76             :     CPLVirtualMemFree(ctxt);
      77             : }
      78             : #endif
      79             : 
      80       50501 : static void test_two_pages_cbk(CPLVirtualMem * /* ctxt */, size_t nOffset,
      81             :                                void *pPageToFill, size_t nPageSize,
      82             :                                void * /* pUserData */)
      83             : {
      84             :     /*fprintfstderr("requesting page %lu (nPageSize=%d), nLRUSize=%d\n",
      85             :             (unsigned long)(nOffset / nPageSize),
      86             :             (int)nPageSize,
      87             :             ctxt->nLRUSize);*/
      88       84168 :     memset(pPageToFill,
      89             :            (nOffset == 0)      ? 0x3F
      90       33667 :            : (nOffset == 4096) ? 0x5F
      91             :                                : 0x7F,
      92             :            nPageSize);
      93       50501 : }
      94             : 
      95             : #define MINIMUM_PAGE_SIZE 4096
      96             : 
      97           1 : static void test_two_pages_thread(void *p)
      98             : {
      99           1 :     CPLVirtualMem *ctxt = (CPLVirtualMem *)p;
     100           1 :     char *addr = (char *)CPLVirtualMemGetAddr(ctxt);
     101             :     int i;
     102           1 :     CPLVirtualMemDeclareThread(ctxt);
     103             :     /*fprintfstderr("aux thread is %X\n", pthread_self());*/
     104             : 
     105       50001 :     for (i = 0; i < 50 * 1000; i++)
     106             :     {
     107       50000 :         char val =
     108       50000 :             addr[MINIMUM_PAGE_SIZE * (i % 3) + MINIMUM_PAGE_SIZE / 2 - 1];
     109             :         /*fprintfstderr("T2: val[%d] = %d\n", MINIMUM_PAGE_SIZE * (i % 2) +
     110             :          * MINIMUM_PAGE_SIZE/2 - 1, val);*/
     111       50000 :         ASSERT_EQ(val, (((i % 3) == 0) ? 0x3F : ((i % 3) == 1) ? 0x5F : 0x7F));
     112             :     }
     113           1 :     CPLVirtualMemUnDeclareThread(ctxt);
     114             : }
     115             : 
     116           1 : static void test_two_pages(CPLVirtualMem *ctxt)
     117             : {
     118             :     volatile char *addr;
     119             :     CPLJoinableThread *hThread;
     120             : 
     121           1 :     printf("test_two_pages()\n");
     122             : 
     123           1 :     addr = (char *)CPLVirtualMemGetAddr(ctxt);
     124           1 :     ASSERT_EQ(CPLVirtualMemGetPageSize(ctxt), MINIMUM_PAGE_SIZE);
     125           1 :     ASSERT_TRUE(CPLVirtualMemIsAccessThreadSafe(ctxt));
     126             :     /*fprintfstderr("main thread is %X, addr=%p\n", pthread_self(), addr);*/
     127           1 :     hThread = CPLCreateJoinableThread(test_two_pages_thread, ctxt);
     128           1 :     CPLVirtualMemDeclareThread(ctxt);
     129             :     {
     130           1 :         int i = 0;
     131       50001 :         for (i = 0; i < 50 * 1000; i++)
     132             :         {
     133       50000 :             char val = addr[MINIMUM_PAGE_SIZE * (i % 3)];
     134             :             /*fprintfstderr("T1: val[%d] = %d\n", MINIMUM_PAGE_SIZE * (i % 2),
     135             :              * val);*/
     136       50000 :             ASSERT_EQ(val, (((i % 3) == 0)   ? 0x3F
     137             :                             : ((i % 3) == 1) ? 0x5F
     138             :                                              : 0x7F));
     139             :         }
     140             :     }
     141           1 :     CPLVirtualMemUnDeclareThread(ctxt);
     142           1 :     CPLJoinThread(hThread);
     143           1 :     CPLVirtualMemFree(ctxt);
     144             : }
     145             : 
     146           4 : static void test_raw_auto(const char *pszFormat, int bFileMapping)
     147             : {
     148           4 :     GDALAllRegister();
     149             : 
     150           4 :     printf("test_raw_auto(format=%s, bFileMapping=%d)\n", pszFormat,
     151             :            bFileMapping);
     152           4 :     if (GDALGetDriverByName(pszFormat) == nullptr)
     153             :     {
     154           0 :         GTEST_SKIP() << pszFormat << " driver missing";
     155             :         return;
     156             :     }
     157             : 
     158           4 :     CPLString osTmpFile;
     159             : 
     160           4 :     if (bFileMapping)
     161             :         osTmpFile =
     162           2 :             CPLResetExtension(CPLGenerateTempFilename(pszFormat), "img");
     163             :     else
     164           2 :         osTmpFile = "/vsimem/tmp.img";
     165             :     GDALDatasetH hDS =
     166           4 :         GDALCreate(GDALGetDriverByName(pszFormat), osTmpFile.c_str(), 400, 300,
     167             :                    2, GDT_Byte, nullptr);
     168           4 :     ASSERT_TRUE(hDS != nullptr);
     169             : 
     170             :     int nPixelSpace1;
     171             :     GIntBig nLineSpace1;
     172             :     int nPixelSpace2;
     173             :     GIntBig nLineSpace2;
     174           4 :     if (!bFileMapping)
     175             :     {
     176             :         char **papszOptions =
     177           2 :             CSLSetNameValue(nullptr, "USE_DEFAULT_IMPLEMENTATION", "NO");
     178           2 :         ASSERT_EQ(GDALGetVirtualMemAuto(GDALGetRasterBand(hDS, 1), GF_Write,
     179             :                                         &nPixelSpace1, &nLineSpace1,
     180             :                                         papszOptions),
     181             :                   nullptr);
     182           2 :         CSLDestroy(papszOptions);
     183             :     }
     184             :     CPLVirtualMem *pVMem1 =
     185           4 :         GDALGetVirtualMemAuto(GDALGetRasterBand(hDS, 1), GF_Write,
     186             :                               &nPixelSpace1, &nLineSpace1, nullptr);
     187           4 :     char **papszOptions = CSLSetNameValue(nullptr, "USE_DEFAULT_IMPLEMENTATION",
     188           4 :                                           (bFileMapping) ? "NO" : "YES");
     189             :     CPLVirtualMem *pVMem2 =
     190           4 :         GDALGetVirtualMemAuto(GDALGetRasterBand(hDS, 2), GF_Write,
     191             :                               &nPixelSpace2, &nLineSpace2, papszOptions);
     192           4 :     CSLDestroy(papszOptions);
     193           4 :     ASSERT_TRUE(pVMem1 != nullptr);
     194           4 :     ASSERT_TRUE(pVMem2 != nullptr);
     195           4 :     ASSERT_EQ(CPLVirtualMemIsFileMapping(pVMem1), bFileMapping);
     196           4 :     ASSERT_EQ(nPixelSpace1,
     197             :               ((EQUAL(pszFormat, "GTIFF") && bFileMapping) ? 2 : 1));
     198           4 :     if (bFileMapping)
     199           2 :         ASSERT_EQ(nLineSpace1, 400 * 2);
     200             :     else
     201           2 :         ASSERT_EQ(nLineSpace1, 400 * nPixelSpace1);
     202             : 
     203           4 :     GByte *pBase1 = (GByte *)CPLVirtualMemGetAddr(pVMem1);
     204           4 :     GByte *pBase2 = (GByte *)CPLVirtualMemGetAddr(pVMem2);
     205        1204 :     for (int j = 0; j < 300; j++)
     206             :     {
     207      481200 :         for (int i = 0; i < 400; i++)
     208             :         {
     209      480000 :             pBase1[j * static_cast<int>(nLineSpace1) + i * nPixelSpace1] = 127;
     210      480000 :             pBase2[j * static_cast<int>(nLineSpace2) + i * nPixelSpace2] = 255;
     211             :         }
     212             :     }
     213             : 
     214           4 :     CPLVirtualMemFree(pVMem1);
     215           4 :     CPLVirtualMemFree(pVMem2);
     216           4 :     GDALClose(hDS);
     217             : 
     218           4 :     hDS = GDALOpen(osTmpFile.c_str(), GA_ReadOnly);
     219           4 :     ASSERT_EQ(GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, 400, 300),
     220             :               52906);
     221           4 :     ASSERT_EQ(GDALChecksumImage(GDALGetRasterBand(hDS, 2), 0, 0, 400, 300),
     222             :               30926);
     223           4 :     GDALClose(hDS);
     224             : 
     225           4 :     GDALDeleteDataset(nullptr, osTmpFile.c_str());
     226             : }
     227             : 
     228           4 : TEST(testvitualmem, test)
     229             : {
     230           1 :     if (getenv("SKIP_TESTVIRTUALMEM") != nullptr)
     231             :     {
     232           0 :         fprintf(stderr, "Skipping testvitualmem\n");  // ok
     233           0 :         return;
     234             :     }
     235             : 
     236             :     /*printf("test_huge_mapping\n");
     237             :     test_huge_mapping();*/
     238             : 
     239           1 :     printf("Physical memory : " CPL_FRMT_GIB " bytes\n", CPLGetPhysicalRAM());
     240             : 
     241           1 :     if (CPLIsVirtualMemFileMapAvailable())
     242             :     {
     243           1 :         printf("Testing CPLVirtualMemFileMapNew()\n");
     244           1 :         VSILFILE *fp = VSIFOpenL(GCORE_DATA_DIR "byte.tif", "rb");
     245           1 :         ASSERT_TRUE(fp != nullptr);
     246           1 :         VSIFSeekL(fp, 0, SEEK_END);
     247           1 :         size_t nSize = (size_t)VSIFTellL(fp);
     248           1 :         VSIFSeekL(fp, 0, SEEK_SET);
     249           1 :         void *pRefBuf = CPLMalloc(nSize);
     250           1 :         VSIFReadL(pRefBuf, 1, nSize, fp);
     251           1 :         CPLVirtualMem *psMem = CPLVirtualMemFileMapNew(
     252             :             fp, 0, nSize, VIRTUALMEM_READONLY, nullptr, nullptr);
     253           1 :         ASSERT_TRUE(psMem != nullptr);
     254           1 :         void *pMemBuf = CPLVirtualMemGetAddr(psMem);
     255           1 :         ASSERT_TRUE(memcmp(pRefBuf, pMemBuf, nSize) == 0);
     256           1 :         CPLFree(pRefBuf);
     257           1 :         CPLVirtualMemFree(psMem);
     258           1 :         VSIFCloseL(fp);
     259             :     }
     260             : 
     261           1 :     auto ctxt = CPLVirtualMemNew(3 * MINIMUM_PAGE_SIZE, MINIMUM_PAGE_SIZE,
     262             :                                  MINIMUM_PAGE_SIZE, FALSE, VIRTUALMEM_READONLY,
     263             :                                  test_two_pages_cbk, nullptr, nullptr, nullptr);
     264           1 :     if (ctxt)
     265             :     {
     266           1 :         test_two_pages(ctxt);
     267           1 :         test_raw_auto("EHDR", TRUE);
     268           1 :         test_raw_auto("EHDR", FALSE);
     269           1 :         test_raw_auto("GTIFF", TRUE);
     270           1 :         test_raw_auto("GTIFF", FALSE);
     271             :     }
     272             : 
     273           1 :     CPLVirtualMemManagerTerminate();
     274           1 :     GDALDestroyDriverManager();
     275             : }
     276             : 
     277             : }  // namespace

Generated by: LCOV version 1.14