LCOV - code coverage report
Current view: top level - tests - catch_virtualseeker.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 138 138 100.0 %
Date: 2015-04-12 Functions: 3 3 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  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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
      20             : */
      21             : 
      22             : /** \file
      23             :  *
      24             :  * Zipios++ unit tests used to verify the VirtualSeeker class.
      25             :  */
      26             : 
      27             : #include "catch_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           1 :     zipios_test::auto_unlink_t auto_unlink("file256.bin");
      51             :     {
      52           1 :         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           1 :         }
      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         256 :         REQUIRE_THROWS_AS(zipios::VirtualSeeker vs(start_offset, -end), zipios::InvalidException);
      77         256 :         REQUIRE_THROWS_AS(zipios::VirtualSeeker vs(-start_offset, -end), zipios::InvalidException);
      78         256 :         if(start_offset != 0)
      79             :         {
      80         255 :             REQUIRE_THROWS_AS(zipios::VirtualSeeker vs(-start_offset, end), zipios::InvalidException);
      81             :         }
      82             : 
      83             :         // the end parameter to the VirtualSeeker is a "weird" position
      84         256 :         zipios::VirtualSeeker vs(start_offset, end);
      85             : 
      86             :         {
      87         256 :             REQUIRE(vs.startOffset() == start_offset);
      88         256 :             REQUIRE(vs.endOffset() == end);
      89             : 
      90             :             zipios::offset_t start_test;
      91             :             zipios::offset_t end_test;
      92         256 :             vs.getOffsets(start_test, end_test);
      93         256 :             REQUIRE(start_test == start_offset);
      94         256 :             REQUIRE(end_test == end);
      95             :         }
      96             : 
      97             :         {
      98         256 :             vs.vseekg(is, 0, std::ios::beg);
      99         256 :             REQUIRE(is.tellg() == start_offset);
     100         256 :             REQUIRE(vs.vtellg(is) == 0);
     101             : 
     102         256 :             size_t const sz(std::min(max_read, FOUR));
     103         256 :             is.read(buf, sz);
     104         256 :             REQUIRE(is.tellg() == static_cast<zipios::offset_t>(start_offset + sz));
     105         256 :             REQUIRE(is);
     106         256 :             if(sz > 0)
     107             :             {
     108         254 :                 REQUIRE(buf[0] == static_cast<char>(start_offset));
     109             :             }
     110         256 :             if(sz > 1)
     111             :             {
     112         253 :                 REQUIRE(buf[1] == static_cast<char>(start_offset + 1));
     113             :             }
     114         256 :             if(sz > 2)
     115             :             {
     116         253 :                 REQUIRE(buf[2] == static_cast<char>(start_offset + 2));
     117             :             }
     118         256 :             if(sz > 3)
     119             :             {
     120         251 :                 REQUIRE(buf[3] == static_cast<char>(start_offset + 3));
     121             :             }
     122             : 
     123             :             // try moving a little more (if max_read allows it)
     124         256 :             if(max_read > 9UL)
     125             :             {
     126         240 :                 vs.vseekg(is, 4, std::ios::cur);
     127         240 :                 REQUIRE(is.tellg() == start_offset + 8);
     128         240 :                 REQUIRE(vs.vtellg(is) == 8);
     129             : 
     130         240 :                 size_t const sz2(std::min(max_read - 8UL, 4UL));
     131         240 :                 is.read(buf, sz2);
     132         240 :                 REQUIRE(is);
     133         240 :                 if(sz2 > 0)
     134             :                 {
     135         240 :                     REQUIRE(buf[0] == static_cast<char>(start_offset + 8));
     136             :                 }
     137         240 :                 if(sz2 > 1)
     138             :                 {
     139         240 :                     REQUIRE(buf[1] == static_cast<char>(start_offset + 8 + 1));
     140             :                 }
     141         240 :                 if(sz2 > 2)
     142             :                 {
     143         238 :                     REQUIRE(buf[2] == static_cast<char>(start_offset + 8 + 2));
     144             :                 }
     145         240 :                 if(sz2 > 3)
     146             :                 {
     147         236 :                     REQUIRE(buf[3] == static_cast<char>(start_offset + 8 + 3));
     148             :                 }
     149             :             }
     150             :         }
     151             : 
     152             :         {
     153         256 :             ssize_t const sz(std::min(max_read, FOUR));
     154             : 
     155         256 :             vs.vseekg(is, -sz, std::ios::end);
     156         256 :             std::streampos const expected_absolute_pos(end_offset - sz);
     157         256 :             REQUIRE(is.tellg() == expected_absolute_pos);
     158         256 :             std::streampos const expected_virtual_pos(end_offset - sz - start_offset);
     159         256 :             REQUIRE(vs.vtellg(is) == expected_virtual_pos);
     160             : 
     161         256 :             is.read(buf, sz);
     162         256 :             REQUIRE(is.tellg() == end_offset);
     163         256 :             REQUIRE(is);
     164         256 :             if(sz > 0)
     165             :             {
     166         254 :                 REQUIRE(buf[0] == static_cast<char>(end_offset - sz));
     167             :             }                                                         
     168         256 :             if(sz > 1)                                                
     169             :             {                                                         
     170         253 :                 REQUIRE(buf[1] == static_cast<char>(end_offset - sz + 1));
     171             :             }                                                         
     172         256 :             if(sz > 2)                                                
     173             :             {                                                         
     174         253 :                 REQUIRE(buf[2] == static_cast<char>(end_offset - sz + 2));
     175             :             }                                                         
     176         256 :             if(sz > 3)                                                
     177             :             {                                                         
     178         251 :                 REQUIRE(buf[3] == static_cast<char>(end_offset - sz + 3));
     179             :             }
     180             : 
     181             :             // try moving a little more (if max_read allows it)
     182         256 :             if(max_read >= 9UL && max_read - 8UL >= static_cast<size_t>(start_offset))
     183             :             {
     184          99 :                 ssize_t const sz2(std::min(max_read - 8UL, 4UL));
     185             : 
     186          99 :                 vs.vseekg(is, -sz2 - sz, std::ios::cur);
     187          99 :                 std::streampos const expected_absolute_pos2(end_offset - sz2 - sz);
     188          99 :                 REQUIRE(is.tellg() == expected_absolute_pos2);
     189          99 :                 std::streampos const expected_virtual_pos2(end_offset - sz2 - sz - start_offset);
     190          99 :                 REQUIRE(vs.vtellg(is) == expected_virtual_pos2);
     191             : 
     192          99 :                 is.read(buf, sz2);
     193          99 :                 REQUIRE(is);
     194          99 :                 if(sz2 > 0)
     195             :                 {
     196          99 :                     REQUIRE(buf[0] == static_cast<char>(end_offset - sz2 - sz));
     197             :                 }
     198          99 :                 if(sz2 > 1)
     199             :                 {
     200          99 :                     REQUIRE(buf[1] == static_cast<char>(end_offset - sz2 - sz + 1));
     201             :                 }
     202          99 :                 if(sz2 > 2)
     203             :                 {
     204          99 :                     REQUIRE(buf[2] == static_cast<char>(end_offset - sz2 - sz + 2));
     205             :                 }
     206          99 :                 if(sz2 > 3)
     207             :                 {
     208          99 :                     REQUIRE(buf[3] == static_cast<char>(end_offset - sz2 - sz + 3));
     209             :                 }
     210             :             }
     211             :         }
     212             : 
     213             :         // change the offset and try again
     214         256 :         zipios::offset_t const start_offset2(rand() % 200);
     215         256 :         zipios::offset_t const end_offset2(start_offset2 + rand() % (256 - start_offset2));
     216         256 :         REQUIRE(start_offset2 <= end_offset2); // this should not happen, period!
     217         256 :         zipios::offset_t const end2(256 - end_offset2);
     218         256 :         size_t max_read2(end_offset2 - start_offset2);
     219             :         // note that the "gap" may be zero
     220             : 
     221             :         // try setting the offsets with invalid values
     222         256 :         REQUIRE_THROWS_AS(vs.setOffsets(-start_offset2, -end2), zipios::InvalidException);
     223         256 :         REQUIRE_THROWS_AS(vs.setOffsets(start_offset2, -end2), zipios::InvalidException);
     224         256 :         if(start_offset2 != 0)
     225             :         {
     226         255 :             REQUIRE_THROWS_AS(vs.setOffsets(-start_offset2, -end2), zipios::InvalidException);
     227             :         }
     228             : 
     229             :         // then change it to a valid value
     230         256 :         vs.setOffsets(start_offset2, end2);
     231             : 
     232             :         {
     233         256 :             REQUIRE(vs.startOffset() == start_offset2);
     234         256 :             REQUIRE(vs.endOffset() == end2);
     235             : 
     236             :             zipios::offset_t start_test2;
     237             :             zipios::offset_t end_test2;
     238         256 :             vs.getOffsets(start_test2, end_test2);
     239         256 :             REQUIRE(start_test2 == start_offset2);
     240         256 :             REQUIRE(end_test2 == end2);
     241             :         }
     242             : 
     243       51712 :         for(int invalid_seek_direction(-100); invalid_seek_direction <= 100; ++invalid_seek_direction)
     244             :         {
     245       51456 :             switch(invalid_seek_direction)
     246             :             {
     247             :             case std::ios::cur:
     248             :             case std::ios::beg:
     249             :             case std::ios::end:
     250         768 :                 break;
     251             : 
     252             :             default:
     253       50688 :                 REQUIRE_THROWS_AS(vs.vseekg(is, 0, static_cast<std::ios::seekdir>(invalid_seek_direction)), std::logic_error);
     254       50688 :                 break;
     255             : 
     256             :             }
     257             :         }
     258             : 
     259             :         {
     260         256 :             vs.vseekg(is, 0, std::ios::beg);
     261         256 :             REQUIRE(vs.vtellg(is) == 0);
     262             : 
     263         256 :             size_t const sz(std::min(max_read2, FOUR));
     264         256 :             is.read(buf, sz);
     265         256 :             REQUIRE(is);
     266         256 :             if(sz > 0)
     267             :             {
     268         254 :                 REQUIRE(buf[0] == static_cast<char>(start_offset2));
     269             :             }
     270         256 :             if(sz > 1)
     271             :             {
     272         253 :                 REQUIRE(buf[1] == static_cast<char>(start_offset2 + 1));
     273             :             }
     274         256 :             if(sz > 2)
     275             :             {
     276         251 :                 REQUIRE(buf[2] == static_cast<char>(start_offset2 + 2));
     277             :             }
     278         256 :             if(sz > 3)
     279             :             {
     280         249 :                 REQUIRE(buf[3] == static_cast<char>(start_offset2 + 3));
     281             :             }
     282             :         }
     283             : 
     284             :         {
     285         256 :             ssize_t const sz(std::min(max_read2, FOUR));
     286             : 
     287         256 :             vs.vseekg(is, -sz, std::ios::end);
     288         256 :             std::streampos const expected_absolute_pos(end_offset2 - sz);
     289         256 :             REQUIRE(is.tellg() == expected_absolute_pos);
     290         256 :             std::streampos const expected_virtual_pos(end_offset2 - sz - start_offset2);
     291         256 :             REQUIRE(vs.vtellg(is) == expected_virtual_pos);
     292             : 
     293         256 :             is.read(buf, sz);
     294         256 :             REQUIRE(is);
     295         256 :             if(sz > 0)
     296             :             {
     297         254 :                 REQUIRE(buf[0] == static_cast<char>(end_offset2 - sz));
     298             :             }                                                         
     299         256 :             if(sz > 1)                                                
     300             :             {                                                         
     301         253 :                 REQUIRE(buf[1] == static_cast<char>(end_offset2 - sz + 1));
     302             :             }                                                         
     303         256 :             if(sz > 2)                                                
     304             :             {                                                         
     305         251 :                 REQUIRE(buf[2] == static_cast<char>(end_offset2 - sz + 2));
     306             :             }                                                         
     307         256 :             if(sz > 3)                                                
     308             :             {                                                         
     309         249 :                 REQUIRE(buf[3] == static_cast<char>(end_offset2 - sz + 3));
     310             :             }
     311             :         }
     312           1 :     }
     313           4 : }
     314             : 
     315             : 
     316             : // vim: ts=4 sw=4 et
     317             : 
     318             : // Local Variables:
     319             : // mode: cpp
     320             : // indent-tabs-mode: nil
     321             : // c-basic-offset: 4
     322             : // tab-width: 4
     323             : // End:

Generated by: LCOV version 1.10