LCOV - code coverage report
Current view: top level - tests - catch_dosdatetime.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 244 244 100.0 %
Date: 2024-06-15 08:26:09 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   Zipios -- a small C++ library that provides easy access to .zip files.
       3             : 
       4             :   Copyright (c) 2019-2022  Made to Order Software Corp.  All Rights Reserved
       5             : 
       6             :   This library is free software; you can redistribute it and/or
       7             :   modify it under the terms of the GNU Lesser General Public
       8             :   License as published by the Free Software Foundation; either
       9             :   version 2.1 of the License, or (at your option) any later version.
      10             : 
      11             :   This library is distributed in the hope that it will be useful,
      12             :   but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :   Lesser General Public License for more details.
      15             : 
      16             :   You should have received a copy of the GNU Lesser General Public
      17             :   License along with this library; if not, write to the Free Software
      18             :   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
      19             : */
      20             : 
      21             : /** \file
      22             :  *
      23             :  * Zipios unit tests verify the dosdatetime.cpp/hpp implementation.
      24             :  *
      25             :  * Keep in mind that the date is saved as a local time date in a zip file.
      26             :  * It's crap. But that comes from the old days of DOS which chose that format
      27             :  * at the time. Sharing between people in the whole world was not viewed in
      28             :  * a way similar to today's world...
      29             :  *
      30             :  * \warning
      31             :  * This test will fail if run around a standard time to a saving time
      32             :  * or a saving time to a standard time changing period (i.e. during the
      33             :  * 1h or so when time changes in spring and autumn.)
      34             :  */
      35             : 
      36             : #include "catch_main.hpp"
      37             : 
      38             : #include <zipios/dosdatetime.hpp>
      39             : #include <zipios/zipiosexceptions.hpp>
      40             : 
      41             : #include <fstream>
      42             : 
      43             : #include <sys/stat.h>
      44             : #include <unistd.h>
      45             : 
      46             : #include <cstring>
      47             : #include <iostream>
      48             : 
      49             : 
      50             : 
      51             : 
      52             : // min = Jan  1, 1980 at 00:00:00
      53             : std::time_t g_minimum_unix = -1;
      54             : 
      55             : // max = Dec 31, 2107 at 23:59:59
      56             : std::time_t g_maximum_unix = -1;
      57             : 
      58             : 
      59           5 : void init_min_max()
      60             : {
      61           5 :     if(g_minimum_unix == -1)
      62             :     {
      63           1 :         struct tm t = {};
      64             : 
      65           1 :         t.tm_sec = 0;
      66           1 :         t.tm_min = 0;
      67           1 :         t.tm_hour = 0;
      68           1 :         t.tm_mday = 1;
      69           1 :         t.tm_mon = 0;
      70           1 :         t.tm_year = 1980 - 1900;
      71           1 :         t.tm_isdst = -1;
      72           1 :         g_minimum_unix = mktime(&t);
      73           1 :         CATCH_REQUIRE((g_minimum_unix & 1) == 0);
      74             :     }
      75             : 
      76           5 :     if(g_maximum_unix == -1)
      77             :     {
      78           1 :         struct tm t = {};
      79             : 
      80           1 :         t.tm_sec = 58;
      81           1 :         t.tm_min = 59;
      82           1 :         t.tm_hour = 23;
      83           1 :         t.tm_mday = 31;
      84           1 :         t.tm_mon = 11;
      85           1 :         t.tm_year = 2107 - 1900;
      86           1 :         t.tm_isdst = -1;
      87           1 :         g_maximum_unix = mktime(&t);
      88           1 :         CATCH_REQUIRE((g_maximum_unix & 1) == 0);
      89             :     }
      90           5 : }
      91             : 
      92             : 
      93             : 
      94           2 : CATCH_TEST_CASE("DOS Date & Time Min/Max", "[dosdatetime]")
      95             : {
      96           2 :     CATCH_START_SECTION("DOS time minimum")
      97             :     {
      98           1 :         zipios::DOSDateTime t;
      99           1 :         t.setYear(1980);
     100           1 :         t.setMonth(1);
     101           1 :         t.setMDay(1);
     102           1 :         t.setHour(0);
     103           1 :         t.setMinute(0);
     104           1 :         t.setSecond(0);
     105           1 :         CATCH_REQUIRE(zipios::DOSDateTime::g_min_dosdatetime == t.getDOSDateTime());
     106             :     }
     107           2 :     CATCH_END_SECTION()
     108             : 
     109           2 :     CATCH_START_SECTION("DOS time maximum")
     110             :     {
     111           1 :         zipios::DOSDateTime t;
     112           1 :         t.setYear(2107);
     113           1 :         t.setMonth(12);
     114           1 :         t.setMDay(31);
     115           1 :         t.setHour(23);
     116           1 :         t.setMinute(59);
     117           1 :         t.setSecond(59);
     118           1 :         CATCH_REQUIRE(zipios::DOSDateTime::g_max_dosdatetime == t.getDOSDateTime());
     119             :     }
     120           2 :     CATCH_END_SECTION()
     121           2 : }
     122             : 
     123             : 
     124           7 : CATCH_TEST_CASE("Invalid DOS Date & Time", "[dosdatetime]")
     125             : {
     126           7 :     CATCH_START_SECTION("daysInMonth() when month is invalid")
     127             :     {
     128             :         // by default the date is 0 which means the month is 0 and
     129             :         // trying to call daysInMonth() fails with -1
     130             :         //
     131           1 :         zipios::DOSDateTime d;
     132           1 :         CATCH_REQUIRE(d.daysInMonth() == -1);
     133             :     }
     134           7 :     CATCH_END_SECTION()
     135             : 
     136           7 :     CATCH_START_SECTION("get/set seconds")
     137             :     {
     138          61 :         for(int i = 0; i < 60; ++i)
     139             :         {
     140          60 :             zipios::DOSDateTime t;
     141          60 :             t.setSecond(i);
     142          60 :             CATCH_REQUIRE(t.getSecond() == (i & -2));
     143             :         }
     144          21 :         for(int i = -20; i < 0; ++i)
     145             :         {
     146          20 :             zipios::DOSDateTime t;
     147          20 :             int const r(rand() % 60);
     148          20 :             t.setSecond(r);
     149          20 :             CATCH_REQUIRE(t.getSecond() == (r & -2));
     150          20 :             CATCH_REQUIRE_THROWS_AS(t.setSecond(i), zipios::InvalidException);
     151          20 :             CATCH_REQUIRE(t.getSecond() == (r & -2));
     152             :         }
     153          22 :         for(int i = 60; i <= 80; ++i)
     154             :         {
     155          21 :             zipios::DOSDateTime t;
     156          21 :             int const r(rand() % 60);
     157          21 :             t.setSecond(r);
     158          21 :             CATCH_REQUIRE(t.getSecond() == (r & -2));
     159          21 :             CATCH_REQUIRE_THROWS_AS(t.setSecond(i), zipios::InvalidException);
     160          21 :             CATCH_REQUIRE(t.getSecond() == (r & -2));
     161             :         }
     162             :     }
     163           7 :     CATCH_END_SECTION()
     164             : 
     165           7 :     CATCH_START_SECTION("get/set minutes")
     166             :     {
     167          61 :         for(int i = 0; i < 60; ++i)
     168             :         {
     169          60 :             zipios::DOSDateTime t;
     170          60 :             t.setMinute(i);
     171          60 :             CATCH_REQUIRE(t.getMinute() == i);
     172             :         }
     173          21 :         for(int i = -20; i < 0; ++i)
     174             :         {
     175          20 :             zipios::DOSDateTime t;
     176          20 :             int const r(rand() % 60);
     177          20 :             t.setMinute(r);
     178          20 :             CATCH_REQUIRE(t.getMinute() == r);
     179          20 :             CATCH_REQUIRE_THROWS_AS(t.setMinute(i), zipios::InvalidException);
     180          20 :             CATCH_REQUIRE(t.getMinute() == r);
     181             :         }
     182          22 :         for(int i = 60; i <= 80; ++i)
     183             :         {
     184          21 :             zipios::DOSDateTime t;
     185          21 :             int const r(rand() % 60);
     186          21 :             t.setMinute(r);
     187          21 :             CATCH_REQUIRE(t.getMinute() == r);
     188          21 :             CATCH_REQUIRE_THROWS_AS(t.setMinute(i), zipios::InvalidException);
     189          21 :             CATCH_REQUIRE(t.getMinute() == r);
     190             :         }
     191             :     }
     192           7 :     CATCH_END_SECTION()
     193             : 
     194           7 :     CATCH_START_SECTION("get/set hours")
     195             :     {
     196          25 :         for(int i = 0; i < 24; ++i)
     197             :         {
     198          24 :             zipios::DOSDateTime t;
     199          24 :             t.setHour(i);
     200          24 :             CATCH_REQUIRE(t.getHour() == i);
     201             :         }
     202          21 :         for(int i = -20; i < 0; ++i)
     203             :         {
     204          20 :             zipios::DOSDateTime t;
     205          20 :             int const r(rand() % 24);
     206          20 :             t.setHour(r);
     207          20 :             CATCH_REQUIRE(t.getHour() == r);
     208          20 :             CATCH_REQUIRE_THROWS_AS(t.setHour(i), zipios::InvalidException);
     209          20 :             CATCH_REQUIRE(t.getHour() == r);
     210             :         }
     211          22 :         for(int i = 24; i <= 44; ++i)
     212             :         {
     213          21 :             zipios::DOSDateTime t;
     214          21 :             int const r(rand() % 24);
     215          21 :             t.setHour(r);
     216          21 :             CATCH_REQUIRE(t.getHour() == r);
     217          21 :             CATCH_REQUIRE_THROWS_AS(t.setHour(i), zipios::InvalidException);
     218          21 :             CATCH_REQUIRE(t.getHour() == r);
     219             :         }
     220             :     }
     221           7 :     CATCH_END_SECTION()
     222             : 
     223             :     // day is limited between 1 and 31 on a setMDay()
     224             :     // use the isValid() to know whether it is valid for the current month
     225             :     // and year
     226             :     //
     227           7 :     CATCH_START_SECTION("get/set day of the month")
     228             :     {
     229          32 :         for(int i = 1; i < 32; ++i)
     230             :         {
     231          31 :             zipios::DOSDateTime t;
     232          31 :             t.setMDay(i);
     233          31 :             CATCH_REQUIRE(t.getMDay() == i);
     234             :         }
     235          22 :         for(int i = -20; i <= 0; ++i)
     236             :         {
     237          21 :             zipios::DOSDateTime t;
     238          21 :             int const r(rand() % 31 + 1);
     239          21 :             t.setMDay(r);
     240          21 :             CATCH_REQUIRE(t.getMDay() == r);
     241          21 :             CATCH_REQUIRE_THROWS_AS(t.setMDay(i), zipios::InvalidException);
     242          21 :             CATCH_REQUIRE(t.getMDay() == r);
     243             :         }
     244          22 :         for(int i = 32; i <= 52; ++i)
     245             :         {
     246          21 :             zipios::DOSDateTime t;
     247          21 :             int const r(rand() % 31 + 1);
     248          21 :             t.setMDay(r);
     249          21 :             CATCH_REQUIRE(t.getMDay() == r);
     250          21 :             CATCH_REQUIRE_THROWS_AS(t.setMDay(i), zipios::InvalidException);
     251          21 :             CATCH_REQUIRE(t.getMDay() == r);
     252             :         }
     253             :     }
     254           7 :     CATCH_END_SECTION()
     255             : 
     256           7 :     CATCH_START_SECTION("get/set month")
     257             :     {
     258          12 :         for(int i = 1; i < 12; ++i)
     259             :         {
     260          11 :             zipios::DOSDateTime t;
     261          11 :             t.setMonth(i);
     262          11 :             CATCH_REQUIRE(t.getMonth() == i);
     263             :         }
     264          22 :         for(int i = -20; i <= 0; ++i)
     265             :         {
     266          21 :             zipios::DOSDateTime t;
     267          21 :             int const r(rand() % 12 + 1);
     268          21 :             t.setMonth(r);
     269          21 :             CATCH_REQUIRE(t.getMonth() == r);
     270          21 :             CATCH_REQUIRE_THROWS_AS(t.setMonth(i), zipios::InvalidException);
     271          21 :             CATCH_REQUIRE(t.getMonth() == r);
     272             :         }
     273          22 :         for(int i = 13; i <= 33; ++i)
     274             :         {
     275          21 :             zipios::DOSDateTime t;
     276          21 :             int const r(rand() % 12 + 1);
     277          21 :             t.setMonth(r);
     278          21 :             CATCH_REQUIRE(t.getMonth() == r);
     279          21 :             CATCH_REQUIRE_THROWS_AS(t.setMonth(i), zipios::InvalidException);
     280          21 :             CATCH_REQUIRE(t.getMonth() == r);
     281             :         }
     282             :     }
     283           7 :     CATCH_END_SECTION()
     284             : 
     285           7 :     CATCH_START_SECTION("get/set year")
     286             :     {
     287         129 :         for(int i = 1980; i <= 2107; ++i)
     288             :         {
     289         128 :             zipios::DOSDateTime t;
     290         128 :             t.setYear(i);
     291         128 :             CATCH_REQUIRE(t.getYear() == i);
     292             :         }
     293         981 :         for(int i = 1000; i < 1980; ++i)
     294             :         {
     295         980 :             zipios::DOSDateTime t;
     296         980 :             int const r(rand() % (2107 - 1980 + 1) + 1980);
     297         980 :             t.setYear(r);
     298         980 :             CATCH_REQUIRE(t.getYear() == r);
     299         980 :             CATCH_REQUIRE_THROWS_AS(t.setYear(i), zipios::InvalidException);
     300         980 :             CATCH_REQUIRE(t.getYear() == r);
     301             :         }
     302          94 :         for(int i = 2108; i <= 2200; ++i)
     303             :         {
     304          93 :             zipios::DOSDateTime t;
     305          93 :             int const r(rand() % (2107 - 1980 + 1) + 1980);
     306          93 :             t.setYear(r);
     307          93 :             CATCH_REQUIRE(t.getYear() == r);
     308          93 :             CATCH_REQUIRE_THROWS_AS(t.setYear(i), zipios::InvalidException);
     309          93 :             CATCH_REQUIRE(t.getYear() == r);
     310             :         }
     311             :     }
     312           7 :     CATCH_END_SECTION()
     313           7 : }
     314             : 
     315             : 
     316             : #if 0
     317             : // this test is too long, which is why it is commented out by default
     318             : // still, it is great if you want to verify all possible DOS Time & Date
     319             : //
     320             : CATCH_TEST_CASE("all_valid_dos_date_n_time", "[dosdatetime]")
     321             : {
     322             :     if(sizeof(std::time_t) < sizeof(uint64_t))
     323             :     {
     324             :         std::cerr << "warning: Unix to DOS time conversion is ignored on platform with a 32 bit time_t definition." << std::endl;
     325             :         return;
     326             :     }
     327             : 
     328             :     init_min_max();
     329             : 
     330             :     CATCH_START_SECTION("all_valid_dos_date_n_time: all valid DOS Date Time values")
     331             :     {
     332             :         // make sure the maximum limit is checked properly
     333             :         //
     334             :         for(std::time_t t(g_minimum_unix); t <= g_maximum_unix; ++t)
     335             :         {
     336             :             std::time_t et((t + 1) & ~1);
     337             : 
     338             :             zipios::DOSDateTime td;
     339             :             CATCH_REQUIRE_FALSE(td.isValid());
     340             :             td.setUnixTimestamp(t);
     341             :             CATCH_REQUIRE(td.isValid());
     342             : 
     343             :             zipios::DOSDateTime::dosdatetime_t const d(td.getDOSDateTime());
     344             : 
     345             :             zipios::DOSDateTime tu;
     346             :             CATCH_REQUIRE_FALSE(tu.isValid());
     347             :             tu.setDOSDateTime(d);
     348             :             CATCH_REQUIRE(tu.isValid());
     349             : 
     350             :             std::time_t const u(tu.getUnixTimestamp());
     351             :             CATCH_REQUIRE(u == et);
     352             :         }
     353             :     }
     354             : }
     355             : #endif
     356             : 
     357             : 
     358           2 : CATCH_TEST_CASE("small_dos_date_n_time", "[dosdatetime]")
     359             : {
     360             :     if(sizeof(std::time_t) < sizeof(uint64_t))
     361             :     {
     362             :         std::cerr << "warning: Unix to DOS time conversion is ignored on platform with a 32 bit time_t definition." << std::endl;
     363             :         return;
     364             :     }
     365             : 
     366           2 :     init_min_max();
     367             : 
     368           2 :     CATCH_START_SECTION("small_dos_date_n_time: just under the minimum")
     369             :     {
     370             :         // make sure the minimum limit is checked properly
     371             :         //
     372             :         // the `g_minimum_unix - 1` is because the function uses the next
     373             :         // event date (i.e. odd seconds get a +1)
     374             :         //
     375          20 :         for(std::time_t t(g_minimum_unix - 20); t < g_minimum_unix - 1; ++t)
     376             :         {
     377          19 :             zipios::DOSDateTime td;
     378          19 :             CATCH_REQUIRE_FALSE(td.isValid());
     379          19 :             CATCH_REQUIRE_THROWS_AS(td.setUnixTimestamp(t), zipios::InvalidException);
     380          19 :             CATCH_REQUIRE_FALSE(td.isValid());
     381             :         }
     382             :     }
     383           2 :     CATCH_END_SECTION()
     384             : 
     385           2 :     CATCH_START_SECTION("small_dos_date_n_time: just around minimum, but valid")
     386             :     {
     387             :         // the "g_minimum_unix - 1" case is peculiar, the Unix date is not
     388             :         // usable as is because it is odd and we're going to use the next
     389             :         // second which means we're getting `minimum_unix` as the date,
     390             :         // which is valid!
     391             :         //
     392          22 :         for(std::time_t t(g_minimum_unix); t <= g_minimum_unix + 20; ++t)
     393             :         {
     394          21 :             std::time_t et((t + 1) & ~1);
     395             : 
     396          21 :             zipios::DOSDateTime td;
     397          21 :             CATCH_REQUIRE_FALSE(td.isValid());
     398          21 :             td.setUnixTimestamp(t);
     399          21 :             CATCH_REQUIRE(td.isValid());
     400             : 
     401          21 :             zipios::DOSDateTime::dosdatetime_t const d(td.getDOSDateTime());
     402             : 
     403          21 :             zipios::DOSDateTime tu;
     404          21 :             CATCH_REQUIRE_FALSE(tu.isValid());
     405          21 :             tu.setDOSDateTime(d);
     406          21 :             CATCH_REQUIRE(tu.isValid());
     407             : 
     408          21 :             std::time_t const u(tu.getUnixTimestamp());
     409          21 :             CATCH_REQUIRE(u == et);
     410             :         }
     411             :     }
     412           2 :     CATCH_END_SECTION()
     413             : }
     414             : 
     415             : 
     416           2 : CATCH_TEST_CASE("large_dos_date_n_time", "[dosdatetime]")
     417             : {
     418             :     if(sizeof(std::time_t) < sizeof(uint64_t))
     419             :     {
     420             :         std::cerr << "warning: Unix to DOS time conversion is ignored on platform with a 32 bit time_t definition." << std::endl;
     421             :         return;
     422             :     }
     423             : 
     424           2 :     init_min_max();
     425             : 
     426           2 :     CATCH_START_SECTION("large_dos_date_n_time: just around maximum, but valid")
     427             :     {
     428             :         // make sure the maximum limit is checked properly
     429             :         //
     430          22 :         for(std::time_t t(g_maximum_unix - 20); t <= g_maximum_unix; ++t)
     431             :         {
     432          21 :             std::time_t et((t + 1) & ~1);
     433             : 
     434          21 :             zipios::DOSDateTime td;
     435          21 :             CATCH_REQUIRE_FALSE(td.isValid());
     436          21 :             td.setUnixTimestamp(t);
     437          21 :             CATCH_REQUIRE(td.isValid());
     438             : 
     439          21 :             zipios::DOSDateTime::dosdatetime_t const d(td.getDOSDateTime());
     440             : 
     441          21 :             zipios::DOSDateTime tu;
     442          21 :             CATCH_REQUIRE_FALSE(tu.isValid());
     443          21 :             tu.setDOSDateTime(d);
     444          21 :             CATCH_REQUIRE(tu.isValid());
     445             : 
     446          21 :             std::time_t const u(tu.getUnixTimestamp());
     447          21 :             CATCH_REQUIRE(u == et);
     448             :         }
     449             :     }
     450           2 :     CATCH_END_SECTION()
     451             : 
     452           2 :     CATCH_START_SECTION("large_dos_date_n_time: just a bit too large")
     453             :     {
     454             :         // make sure the maximum limit is checked properly
     455             :         //
     456          21 :         for(std::time_t t(g_maximum_unix + 1); t <= g_maximum_unix + 20; ++t)
     457             :         {
     458          20 :             zipios::DOSDateTime td;
     459          20 :             CATCH_REQUIRE(td.getDOSDateTime() == 0);
     460          20 :             CATCH_REQUIRE_FALSE(td.isValid());
     461          20 :             CATCH_REQUIRE_THROWS_AS(td.setUnixTimestamp(t), zipios::InvalidException);
     462          20 :             CATCH_REQUIRE_FALSE(td.isValid());
     463          20 :             CATCH_REQUIRE(td.getDOSDateTime() == 0);
     464          20 :             CATCH_REQUIRE(td.getUnixTimestamp() == 0);
     465             :         }
     466             :     }
     467           2 :     CATCH_END_SECTION()
     468             : }
     469             : 
     470             : 
     471             : #if INTPTR_MAX != INT32_MAX
     472             : // at this time only check on 64 bit computers because the DOS date can
     473             : // go out of range in a Unix date when we're on a 32 bit computer
     474           1 : CATCH_TEST_CASE("random_dos_date_n_time", "[dosdatetime]")
     475             : {
     476           1 :     init_min_max();
     477             : 
     478           1 :     CATCH_START_SECTION("random_dos_date_n_time: more random tests")
     479             :     {
     480           1 :         std::time_t const max(sizeof(std::time_t) < sizeof(uint64_t)
     481             :                                 ? 0x7FFFFFFF        // max. in 32 bits is less in Unix time_t than what the DOS Date Time supports
     482             :                                 : 0x104000000LL);   // Dec 31, 2107 23:59:59 is 0x10391447F, so use something a little higher
     483             : 
     484      266319 :         for(std::time_t t(0); t <= max; t += rand() & 0x7FFF)
     485             :         {
     486      266318 :             if(t < g_minimum_unix
     487      246954 :             || t >= g_maximum_unix)
     488             :             {
     489       19812 :                 zipios::DOSDateTime td;
     490       19812 :                 CATCH_REQUIRE_THROWS_AS(td.setUnixTimestamp(t), zipios::InvalidException);
     491       19812 :             }
     492             :             else
     493             :             {
     494      246506 :                 std::time_t et((t + 1) & ~1);
     495             : 
     496      246506 :                 zipios::DOSDateTime td;
     497      246506 :                 td.setUnixTimestamp(t);
     498             : 
     499      246506 :                 zipios::DOSDateTime::dosdatetime_t const d(td.getDOSDateTime());
     500             : 
     501      246506 :                 zipios::DOSDateTime tu;
     502      246506 :                 tu.setDOSDateTime(d);
     503             : 
     504      246506 :                 std::time_t const u(tu.getUnixTimestamp());
     505             : 
     506             :                 // account for possible switch between local times (i.e. PST/PDT)
     507             :                 // (I do not like it, but the Zip format saves dates using
     508             :                 // local time and thus we need to use mktime() to be correct
     509             :                 // but that means we can be off by +/- 1 hour when the time changes)
     510             :                 //
     511             :                 // note that part of the discrepancy is that mktime() can return
     512             :                 // a different value depending what value was last returned because
     513             :                 // tm_isdst = -1 means just that (i.e. there is an internal state)
     514             :                 //
     515      246506 :                 bool const valid(u == et || u == et + 3600 || u == et - 3600);
     516      246506 :                 CATCH_REQUIRE(valid);
     517             :             }
     518             :         }
     519             :     }
     520           1 :     CATCH_END_SECTION()
     521           1 : }
     522             : #endif
     523             : 
     524             : 
     525             : 
     526             : // Local Variables:
     527             : // mode: cpp
     528             : // indent-tabs-mode: nil
     529             : // c-basic-offset: 4
     530             : // tab-width: 4
     531             : // End:
     532             : 
     533             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14

Snap C++ | List of projects | List of versions