LCOV - code coverage report
Current view: top level - tests - virtualseeker.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 136 136 100.0 %
Date: 2019-04-24 14:10:30 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) 2000-2007  Thomas Sondergaard
       5             :   Copyright (C) 2015-2019  Made to Order Software Corporation
       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 "tests.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           2 : TEST_CASE("VirtualSeeker tests", "[zipios_common]")
      48             : {
      49             :     // create a file of 256 bytes
      50           2 :     zipios_test::auto_unlink_t auto_unlink("file256.bin");
      51             :     {
      52           2 :         std::ofstream os("file256.bin", std::ios::out | std::ios::binary);
      53         257 :         for(int i(0); i < 256; ++i)
      54             :         {
      55         256 :             os << static_cast<char>(i);
      56             :         }
      57             :     }
      58             : 
      59             :     // reopen as read-only
      60           2 :     std::ifstream is("file256.bin", std::ios::out | std::ios::binary);
      61             :     char buf[256];
      62             : 
      63         257 :     for(int count(0); count < 256; ++count)
      64             :     {
      65             :         // make the start betwee 0 and 200 so that we have some wiggle room
      66             :         // for the end offset
      67             :         //
      68         256 :         zipios::offset_t const start_offset(rand() % 200);
      69         256 :         zipios::offset_t const end_offset(start_offset + rand() % (256 - start_offset));
      70         256 :         REQUIRE(start_offset <= end_offset); // this should always be true
      71         256 :         zipios::offset_t const end(256 - end_offset);
      72         256 :         size_t const max_read(end_offset - start_offset);
      73             :         // note that the "gap" may be zero
      74             : 
      75             :         // attempt to create the seeker with invalid offsets
      76         512 :         REQUIRE_THROWS_AS([&](){
      77             :                         zipios::VirtualSeeker vs(start_offset, -end);
      78             :                     }(), zipios::InvalidException);
      79         512 :         REQUIRE_THROWS_AS([&](){
      80             :                         zipios::VirtualSeeker vs(-start_offset, -end);
      81             :                     }(), zipios::InvalidException);
      82         256 :         if(start_offset != 0)
      83             :         {
      84         506 :             REQUIRE_THROWS_AS([&](){
      85             :                             zipios::VirtualSeeker vs(-start_offset, end);
      86             :                         }(), zipios::InvalidException);
      87             :         }
      88             : 
      89             :         // the end parameter to the VirtualSeeker is a "weird" position
      90         256 :         zipios::VirtualSeeker vs(start_offset, end);
      91             : 
      92             :         {
      93         256 :             REQUIRE(vs.startOffset() == start_offset);
      94         256 :             REQUIRE(vs.endOffset() == end);
      95             : 
      96             :             zipios::offset_t start_test;
      97             :             zipios::offset_t end_test;
      98         256 :             vs.getOffsets(start_test, end_test);
      99         256 :             REQUIRE(start_test == start_offset);
     100         256 :             REQUIRE(end_test == end);
     101             :         }
     102             : 
     103             :         {
     104         256 :             vs.vseekg(is, 0, std::ios::beg);
     105         256 :             REQUIRE(is.tellg() == start_offset);
     106         256 :             REQUIRE(vs.vtellg(is) == 0);
     107             : 
     108         256 :             size_t const sz(std::min(max_read, FOUR));
     109         256 :             is.read(buf, sz);
     110         256 :             REQUIRE(is.tellg() == static_cast<zipios::offset_t>(start_offset + sz));
     111         256 :             REQUIRE(is);
     112         256 :             if(sz > 0)
     113             :             {
     114         255 :                 REQUIRE(buf[0] == static_cast<char>(start_offset));
     115             :             }
     116         256 :             if(sz > 1)
     117             :             {
     118         252 :                 REQUIRE(buf[1] == static_cast<char>(start_offset + 1));
     119             :             }
     120         256 :             if(sz > 2)
     121             :             {
     122         252 :                 REQUIRE(buf[2] == static_cast<char>(start_offset + 2));
     123             :             }
     124         256 :             if(sz > 3)
     125             :             {
     126         249 :                 REQUIRE(buf[3] == static_cast<char>(start_offset + 3));
     127             :             }
     128             : 
     129             :             // try moving a little more (if max_read allows it)
     130         256 :             if(max_read > 9UL)
     131             :             {
     132         239 :                 vs.vseekg(is, 4, std::ios::cur);
     133         239 :                 REQUIRE(is.tellg() == start_offset + 8);
     134         239 :                 REQUIRE(vs.vtellg(is) == 8);
     135             : 
     136         239 :                 size_t const sz2(std::min(max_read - 8UL, 4UL));
     137         239 :                 is.read(buf, sz2);
     138         239 :                 REQUIRE(is);
     139         239 :                 if(sz2 > 0)
     140             :                 {
     141         239 :                     REQUIRE(buf[0] == static_cast<char>(start_offset + 8));
     142             :                 }
     143         239 :                 if(sz2 > 1)
     144             :                 {
     145         239 :                     REQUIRE(buf[1] == static_cast<char>(start_offset + 8 + 1));
     146             :                 }
     147         239 :                 if(sz2 > 2)
     148             :                 {
     149         235 :                     REQUIRE(buf[2] == static_cast<char>(start_offset + 8 + 2));
     150             :                 }
     151         239 :                 if(sz2 > 3)
     152             :                 {
     153         234 :                     REQUIRE(buf[3] == static_cast<char>(start_offset + 8 + 3));
     154             :                 }
     155             :             }
     156             :         }
     157             : 
     158             :         {
     159         256 :             ssize_t const sz(std::min(max_read, FOUR));
     160             : 
     161         256 :             vs.vseekg(is, -sz, std::ios::end);
     162         256 :             std::streampos const expected_absolute_pos(end_offset - sz);
     163         256 :             REQUIRE(is.tellg() == expected_absolute_pos);
     164         256 :             std::streampos const expected_virtual_pos(end_offset - sz - start_offset);
     165         256 :             REQUIRE(vs.vtellg(is) == expected_virtual_pos);
     166             : 
     167         256 :             is.read(buf, sz);
     168         256 :             REQUIRE(is.tellg() == end_offset);
     169         256 :             REQUIRE(is);
     170         256 :             if(sz > 0)
     171             :             {
     172         255 :                 REQUIRE(buf[0] == static_cast<char>(end_offset - sz));
     173             :             }
     174         256 :             if(sz > 1)
     175             :             {
     176         252 :                 REQUIRE(buf[1] == static_cast<char>(end_offset - sz + 1));
     177             :             }
     178         256 :             if(sz > 2)
     179             :             {
     180         252 :                 REQUIRE(buf[2] == static_cast<char>(end_offset - sz + 2));
     181             :             }
     182         256 :             if(sz > 3)
     183             :             {
     184         249 :                 REQUIRE(buf[3] == static_cast<char>(end_offset - sz + 3));
     185             :             }
     186             : 
     187             :             // try moving a little more (if max_read allows it)
     188         256 :             if(max_read >= 9UL && max_read - 8UL >= static_cast<size_t>(start_offset))
     189             :             {
     190         103 :                 ssize_t const sz2(std::min(max_read - 8UL, 4UL));
     191             : 
     192         103 :                 vs.vseekg(is, -sz2 - sz, std::ios::cur);
     193         103 :                 std::streampos const expected_absolute_pos2(end_offset - sz2 - sz);
     194         103 :                 REQUIRE(is.tellg() == expected_absolute_pos2);
     195         103 :                 std::streampos const expected_virtual_pos2(end_offset - sz2 - sz - start_offset);
     196         103 :                 REQUIRE(vs.vtellg(is) == expected_virtual_pos2);
     197             : 
     198         103 :                 is.read(buf, sz2);
     199         103 :                 REQUIRE(is);
     200         103 :                 if(sz2 > 0)
     201             :                 {
     202         103 :                     REQUIRE(buf[0] == static_cast<char>(end_offset - sz2 - sz));
     203             :                 }
     204         103 :                 if(sz2 > 1)
     205             :                 {
     206         103 :                     REQUIRE(buf[1] == static_cast<char>(end_offset - sz2 - sz + 1));
     207             :                 }
     208         103 :                 if(sz2 > 2)
     209             :                 {
     210         103 :                     REQUIRE(buf[2] == static_cast<char>(end_offset - sz2 - sz + 2));
     211             :                 }
     212         103 :                 if(sz2 > 3)
     213             :                 {
     214         103 :                     REQUIRE(buf[3] == static_cast<char>(end_offset - sz2 - sz + 3));
     215             :                 }
     216             :             }
     217             :         }
     218             : 
     219             :         // change the offset and try again
     220         256 :         zipios::offset_t const start_offset2(rand() % 200);
     221         256 :         zipios::offset_t const end_offset2(start_offset2 + rand() % (256 - start_offset2));
     222         256 :         REQUIRE(start_offset2 <= end_offset2); // this should not happen, period!
     223         256 :         zipios::offset_t const end2(256 - end_offset2);
     224         256 :         size_t max_read2(end_offset2 - start_offset2);
     225             :         // note that the "gap" may be zero
     226             : 
     227             :         // try setting the offsets with invalid values
     228         256 :         REQUIRE_THROWS_AS(vs.setOffsets(-start_offset2, -end2), zipios::InvalidException);
     229         256 :         REQUIRE_THROWS_AS(vs.setOffsets(start_offset2, -end2), zipios::InvalidException);
     230         256 :         if(start_offset2 != 0)
     231             :         {
     232         256 :             REQUIRE_THROWS_AS(vs.setOffsets(-start_offset2, -end2), zipios::InvalidException);
     233             :         }
     234             : 
     235             :         // then change it to a valid value
     236         256 :         vs.setOffsets(start_offset2, end2);
     237             : 
     238             :         {
     239         256 :             REQUIRE(vs.startOffset() == start_offset2);
     240         256 :             REQUIRE(vs.endOffset() == end2);
     241             : 
     242             :             zipios::offset_t start_test2;
     243             :             zipios::offset_t end_test2;
     244         256 :             vs.getOffsets(start_test2, end_test2);
     245         256 :             REQUIRE(start_test2 == start_offset2);
     246         256 :             REQUIRE(end_test2 == end2);
     247             :         }
     248             : 
     249       51712 :         for(int invalid_seek_direction(-100); invalid_seek_direction <= 100; ++invalid_seek_direction)
     250             :         {
     251       51456 :             switch(invalid_seek_direction)
     252             :             {
     253             :             case std::ios::cur:
     254             :             case std::ios::beg:
     255             :             case std::ios::end:
     256         768 :                 break;
     257             : 
     258             :             default:
     259       50688 :                 REQUIRE_THROWS_AS(vs.vseekg(is, 0, static_cast<std::ios::seekdir>(invalid_seek_direction)), std::logic_error);
     260       50688 :                 break;
     261             : 
     262             :             }
     263             :         }
     264             : 
     265             :         {
     266         256 :             vs.vseekg(is, 0, std::ios::beg);
     267         256 :             REQUIRE(vs.vtellg(is) == 0);
     268             : 
     269         256 :             size_t const sz(std::min(max_read2, FOUR));
     270         256 :             is.read(buf, sz);
     271         256 :             REQUIRE(is);
     272         256 :             if(sz > 0)
     273             :             {
     274         256 :                 REQUIRE(buf[0] == static_cast<char>(start_offset2));
     275             :             }
     276         256 :             if(sz > 1)
     277             :             {
     278         250 :                 REQUIRE(buf[1] == static_cast<char>(start_offset2 + 1));
     279             :             }
     280         256 :             if(sz > 2)
     281             :             {
     282         246 :                 REQUIRE(buf[2] == static_cast<char>(start_offset2 + 2));
     283             :             }
     284         256 :             if(sz > 3)
     285             :             {
     286         242 :                 REQUIRE(buf[3] == static_cast<char>(start_offset2 + 3));
     287             :             }
     288             :         }
     289             : 
     290             :         {
     291         256 :             ssize_t const sz(std::min(max_read2, FOUR));
     292             : 
     293         256 :             vs.vseekg(is, -sz, std::ios::end);
     294         256 :             std::streampos const expected_absolute_pos(end_offset2 - sz);
     295         256 :             REQUIRE(is.tellg() == expected_absolute_pos);
     296         256 :             std::streampos const expected_virtual_pos(end_offset2 - sz - start_offset2);
     297         256 :             REQUIRE(vs.vtellg(is) == expected_virtual_pos);
     298             : 
     299         256 :             is.read(buf, sz);
     300         256 :             REQUIRE(is);
     301         256 :             if(sz > 0)
     302             :             {
     303         256 :                 REQUIRE(buf[0] == static_cast<char>(end_offset2 - sz));
     304             :             }
     305         256 :             if(sz > 1)
     306             :             {
     307         250 :                 REQUIRE(buf[1] == static_cast<char>(end_offset2 - sz + 1));
     308             :             }
     309         256 :             if(sz > 2)
     310             :             {
     311         246 :                 REQUIRE(buf[2] == static_cast<char>(end_offset2 - sz + 2));
     312             :             }
     313         256 :             if(sz > 3)
     314             :             {
     315         242 :                 REQUIRE(buf[3] == static_cast<char>(end_offset2 - sz + 3));
     316             :             }
     317             :         }
     318             :     }
     319           4 : }
     320             : 
     321             : 
     322             : // Local Variables:
     323             : // mode: cpp
     324             : // indent-tabs-mode: nil
     325             : // c-basic-offset: 4
     326             : // tab-width: 4
     327             : // End:
     328             : 
     329             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.12