LCOV - code coverage report
Current view: top level - tests - catch_virtualseeker.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 140 140 100.0 %
Date: 2024-06-15 08:26:09 Functions: 4 4 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) 2000-2007  Thomas Sondergaard
       5             :   Copyright (c) 2015-2022  Made to Order Software Corp.  All Rights Reserved
       6             : 
       7             :   This library is free software; you can redistribute it and/or
       8             :   modify it under the terms of the GNU Lesser General Public
       9             :   License as published by the Free Software Foundation; either
      10             :   version 2.1 of the License, or (at your option) any later version.
      11             : 
      12             :   This library is distributed in the hope that it will be useful,
      13             :   but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :   Lesser General Public License for more details.
      16             : 
      17             :   You should have received a copy of the GNU Lesser General Public
      18             :   License along with this library; if not, write to the Free Software
      19             :   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
      20             : */
      21             : 
      22             : /** \file
      23             :  *
      24             :  * Zipios unit tests used to verify the VirtualSeeker class.
      25             :  */
      26             : 
      27             : #include "catch_main.hpp"
      28             : 
      29             : #include <zipios/virtualseeker.hpp>
      30             : #include <zipios/zipiosexceptions.hpp>
      31             : 
      32             : #include <fstream>
      33             : 
      34             : #include <unistd.h>
      35             : 
      36             : 
      37             : namespace
      38             : {
      39             : 
      40             : 
      41             : size_t const FOUR(4);
      42             : 
      43             : 
      44             : } // no name namespace
      45             : 
      46             : 
      47           1 : CATCH_TEST_CASE("VirtualSeeker tests", "[zipios_common]")
      48             : {
      49           1 :     zipios_test::safe_chdir cwd(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
      50             : 
      51             :     // create a file of 256 bytes
      52           2 :     zipios_test::auto_unlink_t auto_unlink("file256.bin", true);
      53             :     {
      54           1 :         std::ofstream os("file256.bin", std::ios::out | std::ios::binary);
      55         257 :         for(int i(0); i < 256; ++i)
      56             :         {
      57         256 :             os << static_cast<char>(i);
      58             :         }
      59           1 :     }
      60             : 
      61             :     // reopen as read-only
      62           1 :     std::ifstream is("file256.bin", std::ios::in | std::ios::binary);
      63             :     char buf[256];
      64             : 
      65         257 :     for(int count(0); count < 256; ++count)
      66             :     {
      67             :         // make the start betwee 0 and 200 so that we have some wiggle room
      68             :         // for the end offset
      69             :         //
      70         256 :         zipios::offset_t const start_offset(rand() % 200);
      71         256 :         zipios::offset_t const end_offset(start_offset + rand() % (256 - start_offset));
      72         256 :         CATCH_REQUIRE(start_offset <= end_offset); // this should always be true
      73         256 :         zipios::offset_t const end(256 - end_offset);
      74         256 :         size_t const max_read(end_offset - start_offset);
      75             :         // note that the "gap" may be zero
      76             : 
      77             :         // attempt to create the seeker with invalid offsets
      78         512 :         CATCH_REQUIRE_THROWS_AS([&](){
      79             :                         zipios::VirtualSeeker vs(start_offset, -end);
      80             :                     }(), zipios::InvalidException);
      81         512 :         CATCH_REQUIRE_THROWS_AS([&](){
      82             :                         zipios::VirtualSeeker vs(-start_offset, -end);
      83             :                     }(), zipios::InvalidException);
      84         256 :         if(start_offset != 0)
      85             :         {
      86         512 :             CATCH_REQUIRE_THROWS_AS([&](){
      87             :                             zipios::VirtualSeeker vs(-start_offset, end);
      88             :                         }(), zipios::InvalidException);
      89             :         }
      90             : 
      91             :         // the end parameter to the VirtualSeeker is a "weird" position
      92         256 :         zipios::VirtualSeeker vs(start_offset, end);
      93             : 
      94             :         {
      95         256 :             CATCH_REQUIRE(vs.startOffset() == start_offset);
      96         256 :             CATCH_REQUIRE(vs.endOffset() == end);
      97             : 
      98             :             zipios::offset_t start_test;
      99             :             zipios::offset_t end_test;
     100         256 :             vs.getOffsets(start_test, end_test);
     101         256 :             CATCH_REQUIRE(start_test == start_offset);
     102         256 :             CATCH_REQUIRE(end_test == end);
     103             :         }
     104             : 
     105             :         {
     106         256 :             vs.vseekg(is, 0, std::ios::beg);
     107         256 :             CATCH_REQUIRE(is.tellg() == start_offset);
     108         256 :             CATCH_REQUIRE(vs.vtellg(is) == 0);
     109             : 
     110         256 :             size_t const sz(std::min(max_read, FOUR));
     111         256 :             is.read(buf, sz);
     112         256 :             CATCH_REQUIRE(is.tellg() == static_cast<zipios::offset_t>(start_offset + sz));
     113         256 :             CATCH_REQUIRE(is);
     114         256 :             if(sz > 0)
     115             :             {
     116         253 :                 CATCH_REQUIRE(buf[0] == static_cast<char>(start_offset));
     117             :             }
     118         256 :             if(sz > 1)
     119             :             {
     120         253 :                 CATCH_REQUIRE(buf[1] == static_cast<char>(start_offset + 1));
     121             :             }
     122         256 :             if(sz > 2)
     123             :             {
     124         251 :                 CATCH_REQUIRE(buf[2] == static_cast<char>(start_offset + 2));
     125             :             }
     126         256 :             if(sz > 3)
     127             :             {
     128         249 :                 CATCH_REQUIRE(buf[3] == static_cast<char>(start_offset + 3));
     129             :             }
     130             : 
     131             :             // try moving a little more (if max_read allows it)
     132         256 :             if(max_read > 9UL)
     133             :             {
     134         235 :                 vs.vseekg(is, 4, std::ios::cur);
     135         235 :                 CATCH_REQUIRE(is.tellg() == start_offset + 8);
     136         235 :                 CATCH_REQUIRE(vs.vtellg(is) == 8);
     137             : 
     138         235 :                 size_t const sz2(std::min(max_read - 8UL, 4UL));
     139         235 :                 is.read(buf, sz2);
     140         235 :                 CATCH_REQUIRE(is);
     141         235 :                 if(sz2 > 0)
     142             :                 {
     143         235 :                     CATCH_REQUIRE(buf[0] == static_cast<char>(start_offset + 8));
     144             :                 }
     145         235 :                 if(sz2 > 1)
     146             :                 {
     147         235 :                     CATCH_REQUIRE(buf[1] == static_cast<char>(start_offset + 8 + 1));
     148             :                 }
     149         235 :                 if(sz2 > 2)
     150             :                 {
     151         233 :                     CATCH_REQUIRE(buf[2] == static_cast<char>(start_offset + 8 + 2));
     152             :                 }
     153         235 :                 if(sz2 > 3)
     154             :                 {
     155         231 :                     CATCH_REQUIRE(buf[3] == static_cast<char>(start_offset + 8 + 3));
     156             :                 }
     157             :             }
     158             :         }
     159             : 
     160             :         {
     161         256 :             ssize_t const sz(std::min(max_read, FOUR));
     162             : 
     163         256 :             vs.vseekg(is, -sz, std::ios::end);
     164         256 :             std::streampos const expected_absolute_pos(end_offset - sz);
     165         256 :             CATCH_REQUIRE(is.tellg() == expected_absolute_pos);
     166         256 :             std::streampos const expected_virtual_pos(end_offset - sz - start_offset);
     167         256 :             CATCH_REQUIRE(vs.vtellg(is) == expected_virtual_pos);
     168             : 
     169         256 :             is.read(buf, sz);
     170         256 :             CATCH_REQUIRE(is.tellg() == end_offset);
     171         256 :             CATCH_REQUIRE(is);
     172         256 :             if(sz > 0)
     173             :             {
     174         253 :                 CATCH_REQUIRE(buf[0] == static_cast<char>(end_offset - sz));
     175             :             }
     176         256 :             if(sz > 1)
     177             :             {
     178         253 :                 CATCH_REQUIRE(buf[1] == static_cast<char>(end_offset - sz + 1));
     179             :             }
     180         256 :             if(sz > 2)
     181             :             {
     182         251 :                 CATCH_REQUIRE(buf[2] == static_cast<char>(end_offset - sz + 2));
     183             :             }
     184         256 :             if(sz > 3)
     185             :             {
     186         249 :                 CATCH_REQUIRE(buf[3] == static_cast<char>(end_offset - sz + 3));
     187             :             }
     188             : 
     189             :             // try moving a little more (if max_read allows it)
     190         256 :             if(max_read >= 9UL && max_read - 8UL >= static_cast<size_t>(start_offset))
     191             :             {
     192          90 :                 ssize_t const sz2(std::min(max_read - 8UL, 4UL));
     193             : 
     194          90 :                 vs.vseekg(is, -sz2 - sz, std::ios::cur);
     195          90 :                 std::streampos const expected_absolute_pos2(end_offset - sz2 - sz);
     196          90 :                 CATCH_REQUIRE(is.tellg() == expected_absolute_pos2);
     197          90 :                 std::streampos const expected_virtual_pos2(end_offset - sz2 - sz - start_offset);
     198          90 :                 CATCH_REQUIRE(vs.vtellg(is) == expected_virtual_pos2);
     199             : 
     200          90 :                 is.read(buf, sz2);
     201          90 :                 CATCH_REQUIRE(is);
     202          90 :                 if(sz2 > 0)
     203             :                 {
     204          90 :                     CATCH_REQUIRE(buf[0] == static_cast<char>(end_offset - sz2 - sz));
     205             :                 }
     206          90 :                 if(sz2 > 1)
     207             :                 {
     208          90 :                     CATCH_REQUIRE(buf[1] == static_cast<char>(end_offset - sz2 - sz + 1));
     209             :                 }
     210          90 :                 if(sz2 > 2)
     211             :                 {
     212          90 :                     CATCH_REQUIRE(buf[2] == static_cast<char>(end_offset - sz2 - sz + 2));
     213             :                 }
     214          90 :                 if(sz2 > 3)
     215             :                 {
     216          90 :                     CATCH_REQUIRE(buf[3] == static_cast<char>(end_offset - sz2 - sz + 3));
     217             :                 }
     218             :             }
     219             :         }
     220             : 
     221             :         // change the offset and try again
     222         256 :         zipios::offset_t const start_offset2(rand() % 200);
     223         256 :         zipios::offset_t const end_offset2(start_offset2 + rand() % (256 - start_offset2));
     224         256 :         CATCH_REQUIRE(start_offset2 <= end_offset2); // this should not happen, period!
     225         256 :         zipios::offset_t const end2(256 - end_offset2);
     226         256 :         size_t max_read2(end_offset2 - start_offset2);
     227             :         // note that the "gap" may be zero
     228             : 
     229             :         // try setting the offsets with invalid values
     230         256 :         CATCH_REQUIRE_THROWS_AS(vs.setOffsets(-start_offset2, -end2), zipios::InvalidException);
     231         256 :         CATCH_REQUIRE_THROWS_AS(vs.setOffsets(start_offset2, -end2), zipios::InvalidException);
     232         256 :         if(start_offset2 != 0)
     233             :         {
     234         256 :             CATCH_REQUIRE_THROWS_AS(vs.setOffsets(-start_offset2, -end2), zipios::InvalidException);
     235             :         }
     236             : 
     237             :         // then change it to a valid value
     238         256 :         vs.setOffsets(start_offset2, end2);
     239             : 
     240             :         {
     241         256 :             CATCH_REQUIRE(vs.startOffset() == start_offset2);
     242         256 :             CATCH_REQUIRE(vs.endOffset() == end2);
     243             : 
     244             :             zipios::offset_t start_test2;
     245             :             zipios::offset_t end_test2;
     246         256 :             vs.getOffsets(start_test2, end_test2);
     247         256 :             CATCH_REQUIRE(start_test2 == start_offset2);
     248         256 :             CATCH_REQUIRE(end_test2 == end2);
     249             :         }
     250             : 
     251       51712 :         for(int invalid_seek_direction(-100); invalid_seek_direction <= 100; ++invalid_seek_direction)
     252             :         {
     253       51456 :             switch(invalid_seek_direction)
     254             :             {
     255         768 :             case std::ios::cur:
     256             :             case std::ios::beg:
     257             :             case std::ios::end:
     258         768 :                 break;
     259             : 
     260       50688 :             default:
     261       50688 :                 CATCH_REQUIRE_THROWS_AS(vs.vseekg(is, 0, static_cast<std::ios::seekdir>(invalid_seek_direction)), std::logic_error);
     262       50688 :                 break;
     263             : 
     264             :             }
     265             :         }
     266             : 
     267             :         {
     268         256 :             vs.vseekg(is, 0, std::ios::beg);
     269         256 :             CATCH_REQUIRE(vs.vtellg(is) == 0);
     270             : 
     271         256 :             size_t const sz(std::min(max_read2, FOUR));
     272         256 :             is.read(buf, sz);
     273         256 :             CATCH_REQUIRE(is);
     274         256 :             if(sz > 0)
     275             :             {
     276         254 :                 CATCH_REQUIRE(buf[0] == static_cast<char>(start_offset2));
     277             :             }
     278         256 :             if(sz > 1)
     279             :             {
     280         253 :                 CATCH_REQUIRE(buf[1] == static_cast<char>(start_offset2 + 1));
     281             :             }
     282         256 :             if(sz > 2)
     283             :             {
     284         250 :                 CATCH_REQUIRE(buf[2] == static_cast<char>(start_offset2 + 2));
     285             :             }
     286         256 :             if(sz > 3)
     287             :             {
     288         249 :                 CATCH_REQUIRE(buf[3] == static_cast<char>(start_offset2 + 3));
     289             :             }
     290             :         }
     291             : 
     292             :         {
     293         256 :             ssize_t const sz(std::min(max_read2, FOUR));
     294             : 
     295         256 :             vs.vseekg(is, -sz, std::ios::end);
     296         256 :             std::streampos const expected_absolute_pos(end_offset2 - sz);
     297         256 :             CATCH_REQUIRE(is.tellg() == expected_absolute_pos);
     298         256 :             std::streampos const expected_virtual_pos(end_offset2 - sz - start_offset2);
     299         256 :             CATCH_REQUIRE(vs.vtellg(is) == expected_virtual_pos);
     300             : 
     301         256 :             is.read(buf, sz);
     302         256 :             CATCH_REQUIRE(is);
     303         256 :             if(sz > 0)
     304             :             {
     305         254 :                 CATCH_REQUIRE(buf[0] == static_cast<char>(end_offset2 - sz));
     306             :             }
     307         256 :             if(sz > 1)
     308             :             {
     309         253 :                 CATCH_REQUIRE(buf[1] == static_cast<char>(end_offset2 - sz + 1));
     310             :             }
     311         256 :             if(sz > 2)
     312             :             {
     313         250 :                 CATCH_REQUIRE(buf[2] == static_cast<char>(end_offset2 - sz + 2));
     314             :             }
     315         256 :             if(sz > 3)
     316             :             {
     317         249 :                 CATCH_REQUIRE(buf[3] == static_cast<char>(end_offset2 - sz + 3));
     318             :             }
     319             :         }
     320             :     }
     321           1 : }
     322             : 
     323             : 
     324             : // Local Variables:
     325             : // mode: cpp
     326             : // indent-tabs-mode: nil
     327             : // c-basic-offset: 4
     328             : // tab-width: 4
     329             : // End:
     330             : 
     331             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14

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