LCOV - code coverage report
Current view: top level - autotest/cpp - testvirtualmem.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 96 99 97.0 %
Date: 2025-01-18 12:42:00 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL algorithms
       4             :  * Purpose:  Test Delaunay triangulation
       5             :  * Author:   Even Rouault, even.rouault at spatialys.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2014, Even Rouault <even.rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "cpl_multiproc.h"
      14             : #include "cpl_string.h"
      15             : #include "cpl_virtualmem.h"
      16             : #include "gdal_alg.h"
      17             : #include "gdal.h"
      18             : 
      19             : #include "gtest_include.h"
      20             : 
      21             : #include "test_data.h"
      22             : 
      23             : namespace
      24             : {
      25             : 
      26             : // ---------------------------------------------------------------------------
      27             : 
      28             : #ifdef notdef
      29             : static void test_huge_mapping_cbk(CPLVirtualMem *ctxt, size_t nOffset,
      30             :                                   void *pPageToFill, size_t nPageSize,
      31             :                                   void *pUserData)
      32             : {
      33             :     /*fprintfstderr("requesting page %lu (nPageSize=%d), nLRUSize=%d\n",
      34             :             (unsigned long)(nOffset / nPageSize),
      35             :             (int)nPageSize,
      36             :             ctxt->nLRUSize);*/
      37             :     memset(pPageToFill, 0x7F, nPageSize);
      38             : }
      39             : 
      40             : static void test_huge_mapping()
      41             : {
      42             :     CPLVirtualMem *ctxt;
      43             :     char *addr;
      44             :     int i;
      45             : 
      46             :     ctxt = CPLVirtualMemNew(
      47             :         (size_t)10000 * 1024 * 1024, (size_t)2000 * 1024 * 1024, 0, TRUE,
      48             :         VIRTUALMEM_READONLY, test_huge_mapping_cbk, NULL, NULL, NULL);
      49             :     ASSERT_TRUE(ctxt != nullptr);
      50             :     addr = (char *)CPLVirtualMemGetAddr(ctxt);
      51             :     for (i = 0; i < 50 * 1000; i++)
      52             :     {
      53             :         unsigned int seedp;
      54             :         size_t idx = (size_t)rand_r(&seedp) * 3000 * 1024 / RAND_MAX * 1024;
      55             :         char val = addr[idx];
      56             :         /*printf("i=%d, val[%ld] = %d\n", i, (long int)idx, val);*/
      57             :         ASSERT_EQ(val, 0x7F);
      58             :     }
      59             :     CPLVirtualMemFree(ctxt);
      60             : }
      61             : #endif
      62             : 
      63       68558 : static void test_two_pages_cbk(CPLVirtualMem * /* ctxt */, size_t nOffset,
      64             :                                void *pPageToFill, size_t nPageSize,
      65             :                                void * /* pUserData */)
      66             : {
      67             :     /*fprintfstderr("requesting page %lu (nPageSize=%d), nLRUSize=%d\n",
      68             :             (unsigned long)(nOffset / nPageSize),
      69             :             (int)nPageSize,
      70             :             ctxt->nLRUSize);*/
      71      114263 :     memset(pPageToFill,
      72             :            (nOffset == 0)      ? 0x3F
      73       45705 :            : (nOffset == 4096) ? 0x5F
      74             :                                : 0x7F,
      75             :            nPageSize);
      76       68558 : }
      77             : 
      78             : #define MINIMUM_PAGE_SIZE 4096
      79             : 
      80           1 : static void test_two_pages_thread(void *p)
      81             : {
      82           1 :     CPLVirtualMem *ctxt = (CPLVirtualMem *)p;
      83           1 :     char *addr = (char *)CPLVirtualMemGetAddr(ctxt);
      84             :     int i;
      85           1 :     CPLVirtualMemDeclareThread(ctxt);
      86             :     /*fprintfstderr("aux thread is %X\n", pthread_self());*/
      87             : 
      88       50001 :     for (i = 0; i < 50 * 1000; i++)
      89             :     {
      90       50000 :         char val =
      91       50000 :             addr[MINIMUM_PAGE_SIZE * (i % 3) + MINIMUM_PAGE_SIZE / 2 - 1];
      92             :         /*fprintfstderr("T2: val[%d] = %d\n", MINIMUM_PAGE_SIZE * (i % 2) +
      93             :          * MINIMUM_PAGE_SIZE/2 - 1, val);*/
      94       50000 :         ASSERT_EQ(val, (((i % 3) == 0) ? 0x3F : ((i % 3) == 1) ? 0x5F : 0x7F));
      95             :     }
      96           1 :     CPLVirtualMemUnDeclareThread(ctxt);
      97             : }
      98             : 
      99           1 : static void test_two_pages(CPLVirtualMem *ctxt)
     100             : {
     101             :     volatile char *addr;
     102             :     CPLJoinableThread *hThread;
     103             : 
     104           1 :     printf("test_two_pages()\n");
     105             : 
     106           1 :     addr = (char *)CPLVirtualMemGetAddr(ctxt);
     107           1 :     ASSERT_EQ(CPLVirtualMemGetPageSize(ctxt), MINIMUM_PAGE_SIZE);
     108           1 :     ASSERT_TRUE(CPLVirtualMemIsAccessThreadSafe(ctxt));
     109             :     /*fprintfstderr("main thread is %X, addr=%p\n", pthread_self(), addr);*/
     110           1 :     hThread = CPLCreateJoinableThread(test_two_pages_thread, ctxt);
     111           1 :     CPLVirtualMemDeclareThread(ctxt);
     112             :     {
     113           1 :         int i = 0;
     114       50001 :         for (i = 0; i < 50 * 1000; i++)
     115             :         {
     116       50000 :             char val = addr[MINIMUM_PAGE_SIZE * (i % 3)];
     117             :             /*fprintfstderr("T1: val[%d] = %d\n", MINIMUM_PAGE_SIZE * (i % 2),
     118             :              * val);*/
     119       50000 :             ASSERT_EQ(val, (((i % 3) == 0)   ? 0x3F
     120             :                             : ((i % 3) == 1) ? 0x5F
     121             :                                              : 0x7F));
     122             :         }
     123             :     }
     124           1 :     CPLVirtualMemUnDeclareThread(ctxt);
     125           1 :     CPLJoinThread(hThread);
     126           1 :     CPLVirtualMemFree(ctxt);
     127             : }
     128             : 
     129           4 : static void test_raw_auto(const char *pszFormat, int bFileMapping)
     130             : {
     131           4 :     GDALAllRegister();
     132             : 
     133           4 :     printf("test_raw_auto(format=%s, bFileMapping=%d)\n", pszFormat,
     134             :            bFileMapping);
     135           4 :     if (GDALGetDriverByName(pszFormat) == nullptr)
     136             :     {
     137           0 :         GTEST_SKIP() << pszFormat << " driver missing";
     138             :         return;
     139             :     }
     140             : 
     141           4 :     CPLString osTmpFile;
     142             : 
     143           4 :     if (bFileMapping)
     144           2 :         osTmpFile = CPLResetExtensionSafe(
     145           4 :             CPLGenerateTempFilenameSafe(pszFormat).c_str(), "img");
     146             :     else
     147           2 :         osTmpFile = "/vsimem/tmp.img";
     148             :     GDALDatasetH hDS =
     149           4 :         GDALCreate(GDALGetDriverByName(pszFormat), osTmpFile.c_str(), 400, 300,
     150             :                    2, GDT_Byte, nullptr);
     151           4 :     ASSERT_TRUE(hDS != nullptr);
     152             : 
     153             :     int nPixelSpace1;
     154             :     GIntBig nLineSpace1;
     155             :     int nPixelSpace2;
     156             :     GIntBig nLineSpace2;
     157           4 :     if (!bFileMapping)
     158             :     {
     159             :         char **papszOptions =
     160           2 :             CSLSetNameValue(nullptr, "USE_DEFAULT_IMPLEMENTATION", "NO");
     161           2 :         ASSERT_EQ(GDALGetVirtualMemAuto(GDALGetRasterBand(hDS, 1), GF_Write,
     162             :                                         &nPixelSpace1, &nLineSpace1,
     163             :                                         papszOptions),
     164             :                   nullptr);
     165           2 :         CSLDestroy(papszOptions);
     166             :     }
     167             :     CPLVirtualMem *pVMem1 =
     168           4 :         GDALGetVirtualMemAuto(GDALGetRasterBand(hDS, 1), GF_Write,
     169             :                               &nPixelSpace1, &nLineSpace1, nullptr);
     170           4 :     char **papszOptions = CSLSetNameValue(nullptr, "USE_DEFAULT_IMPLEMENTATION",
     171           4 :                                           (bFileMapping) ? "NO" : "YES");
     172             :     CPLVirtualMem *pVMem2 =
     173           4 :         GDALGetVirtualMemAuto(GDALGetRasterBand(hDS, 2), GF_Write,
     174             :                               &nPixelSpace2, &nLineSpace2, papszOptions);
     175           4 :     CSLDestroy(papszOptions);
     176           4 :     ASSERT_TRUE(pVMem1 != nullptr);
     177           4 :     ASSERT_TRUE(pVMem2 != nullptr);
     178           4 :     ASSERT_EQ(CPLVirtualMemIsFileMapping(pVMem1), bFileMapping);
     179           4 :     ASSERT_EQ(nPixelSpace1,
     180             :               ((EQUAL(pszFormat, "GTIFF") && bFileMapping) ? 2 : 1));
     181           4 :     if (bFileMapping)
     182           2 :         ASSERT_EQ(nLineSpace1, 400 * 2);
     183             :     else
     184           2 :         ASSERT_EQ(nLineSpace1, 400 * nPixelSpace1);
     185             : 
     186           4 :     GByte *pBase1 = (GByte *)CPLVirtualMemGetAddr(pVMem1);
     187           4 :     GByte *pBase2 = (GByte *)CPLVirtualMemGetAddr(pVMem2);
     188        1204 :     for (int j = 0; j < 300; j++)
     189             :     {
     190      481200 :         for (int i = 0; i < 400; i++)
     191             :         {
     192      480000 :             pBase1[j * static_cast<int>(nLineSpace1) + i * nPixelSpace1] = 127;
     193      480000 :             pBase2[j * static_cast<int>(nLineSpace2) + i * nPixelSpace2] = 255;
     194             :         }
     195             :     }
     196             : 
     197           4 :     CPLVirtualMemFree(pVMem1);
     198           4 :     CPLVirtualMemFree(pVMem2);
     199           4 :     GDALClose(hDS);
     200             : 
     201           4 :     hDS = GDALOpen(osTmpFile.c_str(), GA_ReadOnly);
     202           4 :     ASSERT_EQ(GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, 400, 300),
     203             :               52906);
     204           4 :     ASSERT_EQ(GDALChecksumImage(GDALGetRasterBand(hDS, 2), 0, 0, 400, 300),
     205             :               30926);
     206           4 :     GDALClose(hDS);
     207             : 
     208           4 :     GDALDeleteDataset(nullptr, osTmpFile.c_str());
     209             : }
     210             : 
     211           4 : TEST(testvitualmem, test)
     212             : {
     213           1 :     if (getenv("SKIP_TESTVIRTUALMEM") != nullptr)
     214             :     {
     215           0 :         fprintf(stderr, "Skipping testvitualmem\n");  // ok
     216           0 :         return;
     217             :     }
     218             : 
     219             :     /*printf("test_huge_mapping\n");
     220             :     test_huge_mapping();*/
     221             : 
     222           1 :     printf("Physical memory : " CPL_FRMT_GIB " bytes\n", CPLGetPhysicalRAM());
     223             : 
     224           1 :     if (CPLIsVirtualMemFileMapAvailable())
     225             :     {
     226           1 :         printf("Testing CPLVirtualMemFileMapNew()\n");
     227           1 :         VSILFILE *fp = VSIFOpenL(GCORE_DATA_DIR "byte.tif", "rb");
     228           1 :         ASSERT_TRUE(fp != nullptr);
     229           1 :         VSIFSeekL(fp, 0, SEEK_END);
     230           1 :         size_t nSize = (size_t)VSIFTellL(fp);
     231           1 :         VSIFSeekL(fp, 0, SEEK_SET);
     232           1 :         void *pRefBuf = CPLMalloc(nSize);
     233           1 :         VSIFReadL(pRefBuf, 1, nSize, fp);
     234           1 :         CPLVirtualMem *psMem = CPLVirtualMemFileMapNew(
     235             :             fp, 0, nSize, VIRTUALMEM_READONLY, nullptr, nullptr);
     236           1 :         ASSERT_TRUE(psMem != nullptr);
     237           1 :         void *pMemBuf = CPLVirtualMemGetAddr(psMem);
     238           1 :         ASSERT_TRUE(memcmp(pRefBuf, pMemBuf, nSize) == 0);
     239           1 :         CPLFree(pRefBuf);
     240           1 :         CPLVirtualMemFree(psMem);
     241           1 :         VSIFCloseL(fp);
     242             :     }
     243             : 
     244           1 :     auto ctxt = CPLVirtualMemNew(3 * MINIMUM_PAGE_SIZE, MINIMUM_PAGE_SIZE,
     245             :                                  MINIMUM_PAGE_SIZE, FALSE, VIRTUALMEM_READONLY,
     246             :                                  test_two_pages_cbk, nullptr, nullptr, nullptr);
     247           1 :     if (ctxt)
     248             :     {
     249           1 :         test_two_pages(ctxt);
     250           1 :         test_raw_auto("EHDR", TRUE);
     251           1 :         test_raw_auto("EHDR", FALSE);
     252           1 :         test_raw_auto("GTIFF", TRUE);
     253           1 :         test_raw_auto("GTIFF", FALSE);
     254             :     }
     255             : 
     256           1 :     CPLVirtualMemManagerTerminate();
     257           1 :     GDALDestroyDriverManager();
     258             : }
     259             : 
     260             : }  // namespace

Generated by: LCOV version 1.14