LCOV - code coverage report
Current view: top level - tests - catch_file.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 290 290 100.0 %
Date: 2023-06-11 18:21:25 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2019-2023  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/safepasswords
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software: you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation, either version 3 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program 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
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License
      17             : // along with this program.  If not, see <https://www.gnu.org/licenses/>.
      18             : 
      19             : // self
      20             : //
      21             : #include    "catch_main.h"
      22             : 
      23             : 
      24             : // safepasswords
      25             : //
      26             : #include    <safepasswords/file.h>
      27             : 
      28             : #include    <safepasswords/exception.h>
      29             : 
      30             : 
      31             : // snapdev
      32             : //
      33             : #include    <snapdev/hexadecimal_string.h>
      34             : #include    <snapdev/not_used.h>
      35             : 
      36             : 
      37             : // libutf8
      38             : //
      39             : #include    <libutf8/libutf8.h>
      40             : 
      41             : 
      42             : // C++
      43             : //
      44             : #include    <set>
      45             : 
      46             : 
      47             : // C
      48             : //
      49             : #include    <malloc.h>
      50             : 
      51             : 
      52             : // last include
      53             : //
      54             : #include    <snapdev/poison.h>
      55             : 
      56             : 
      57             : 
      58             : namespace
      59             : {
      60             : 
      61             : 
      62          11 : std::string get_tmp_dir(char const * filename)
      63             : {
      64          22 :     return SNAP_CATCH2_NAMESPACE::g_tmp_dir() + '/' + filename;
      65             : }
      66             : 
      67             : 
      68             : }
      69             : // no name namespace
      70             : 
      71             : 
      72             : 
      73           1 : CATCH_TEST_CASE("file_load", "[file][load][save]")
      74             : {
      75           1 :     CATCH_START_SECTION("file_load: create file with a few entries")
      76             :     {
      77           1 :         std::string const filename(get_tmp_dir("entries.pwd"));
      78             :         {
      79           1 :             std::ofstream out;
      80           1 :             out.open(filename);
      81           1 :             CATCH_REQUIRE(out.is_open());
      82             : 
      83             :             // valid entries
      84             :             //
      85             :             out << "name:sha512:"
      86           2 :                 << snapdev::bin_to_hex("salt--0123456789")
      87             :                 << ':'
      88           2 :                 << snapdev::bin_to_hex("encrypted-password")
      89           3 :                 << '\n';
      90             :             out << "user:sha3-224:"
      91           2 :                 << snapdev::bin_to_hex("the-salt-is-1234")
      92             :                 << ':'
      93           2 :                 << snapdev::bin_to_hex("another-secret-password")
      94           3 :                 << '\n';
      95             :             out << "walker:sha3-256:"
      96           2 :                 << snapdev::bin_to_hex("salt-is-16bytes!")
      97             :                 << ':'
      98           2 :                 << snapdev::bin_to_hex("you'll never find this_passworD1")
      99           3 :                 << '\n';
     100             :             out << "alexa:md5:"
     101           2 :                 << snapdev::bin_to_hex("more salt here..")
     102             :                 << ':'
     103           2 :                 << snapdev::bin_to_hex("wonder what the password is?")
     104           3 :                 << '\n';
     105             :             out << "lexa:sha1:"
     106           2 :                 << snapdev::bin_to_hex("salt is randomiz")
     107             :                 << ':'
     108           2 :                 << snapdev::bin_to_hex("and SHA1 is really bad, don't use it")
     109           3 :                 << '\n';
     110             :             out << "lex:sha3-256:"
     111           2 :                 << snapdev::bin_to_hex("short name here!")
     112             :                 << ':'
     113           2 :                 << snapdev::bin_to_hex("old version would not find \"lex\" when we have \"alexa\" and \"lexa\" before...")
     114           3 :                 << '\n';
     115             : 
     116             :             // invalid entries
     117             :             //
     118             :             out << "no-password:sha3-256:"
     119           2 :                 << snapdev::bin_to_hex("salt-is-16bytes!")
     120           2 :                 << '\n';
     121             :             out << "missing-salt:sha3-256"
     122           1 :                 << '\n';
     123             :             out << "without-digest"     // this means we do not find that user
     124           1 :                 << '\n';
     125             : 
     126             :             // MUST BE LAST -- ADD MORE BEFORE THIS ENTRY
     127             :             // invalid entry -- the "\n" is missing
     128             :             //
     129           1 :             out << "missing:newline:character:here";
     130           1 :         }
     131           1 :         safepasswords::file f(filename);
     132           1 :         safepasswords::password p;
     133             : 
     134             :         // first try one which does not exist
     135             :         //
     136           1 :         CATCH_REQUIRE_FALSE(f.find("anyone", p));
     137             : 
     138           1 :         CATCH_REQUIRE(f.find("name", p));
     139           1 :         CATCH_REQUIRE(p.get_plain().empty());
     140           1 :         CATCH_REQUIRE(p.get_digest() == "sha512");
     141           1 :         CATCH_REQUIRE(p.get_salt() == "salt--0123456789");
     142           1 :         CATCH_REQUIRE(p.get_encrypted() == "encrypted-password");
     143             : 
     144           1 :         CATCH_REQUIRE(f.find("user", p));
     145           1 :         CATCH_REQUIRE(p.get_plain().empty());
     146           1 :         CATCH_REQUIRE(p.get_digest() == "sha3-224");
     147           1 :         CATCH_REQUIRE(p.get_salt() == "the-salt-is-1234");
     148           1 :         CATCH_REQUIRE(p.get_encrypted() == "another-secret-password");
     149             : 
     150           1 :         CATCH_REQUIRE(f.find("walker", p));
     151           1 :         CATCH_REQUIRE(p.get_plain().empty());
     152           1 :         CATCH_REQUIRE(p.get_digest() == "sha3-256");
     153           1 :         CATCH_REQUIRE(p.get_salt() == "salt-is-16bytes!");
     154           1 :         CATCH_REQUIRE(p.get_encrypted() == "you'll never find this_passworD1");
     155             : 
     156           1 :         CATCH_REQUIRE(f.find("alexa", p));
     157           1 :         CATCH_REQUIRE(p.get_plain().empty());
     158           1 :         CATCH_REQUIRE(p.get_digest() == "md5");
     159           1 :         CATCH_REQUIRE(p.get_salt() == "more salt here..");
     160           1 :         CATCH_REQUIRE(p.get_encrypted() == "wonder what the password is?");
     161             : 
     162           1 :         CATCH_REQUIRE(f.find("lexa", p));
     163           1 :         CATCH_REQUIRE(p.get_plain().empty());
     164           1 :         CATCH_REQUIRE(p.get_digest() == "sha1");
     165           1 :         CATCH_REQUIRE(p.get_salt() == "salt is randomiz");
     166           1 :         CATCH_REQUIRE(p.get_encrypted() == "and SHA1 is really bad, don't use it");
     167             : 
     168           1 :         CATCH_REQUIRE(f.find("lex", p));
     169           1 :         CATCH_REQUIRE(p.get_plain().empty());
     170           1 :         CATCH_REQUIRE(p.get_digest() == "sha3-256");
     171           1 :         CATCH_REQUIRE(p.get_salt() == "short name here!");
     172           1 :         CATCH_REQUIRE(p.get_encrypted() == "old version would not find \"lex\" when we have \"alexa\" and \"lexa\" before...");
     173             : 
     174           1 :         CATCH_REQUIRE_FALSE(f.find("no-password", p));
     175           1 :         CATCH_REQUIRE_FALSE(f.find("missing-salt", p));
     176           1 :         CATCH_REQUIRE_FALSE(f.find("without-digest", p));
     177             : 
     178           1 :         CATCH_REQUIRE_FALSE(f.find("missing", p)); // newline not in string
     179             : 
     180             :         // these reset the password
     181             :         //
     182           1 :         CATCH_REQUIRE(p.get_plain().empty());
     183           1 :         CATCH_REQUIRE(p.get_digest() == "sha3-256");
     184           1 :         CATCH_REQUIRE(p.get_salt().empty());
     185             : 
     186           1 :         CATCH_REQUIRE_FALSE(p.get_encrypted().empty()); // this regenerates a new password
     187             : 
     188           1 :         f.save("some_new_user", p);
     189             : 
     190             :         // also try replacing an existing user
     191             :         //
     192           1 :         safepasswords::password q;
     193           1 :         CATCH_REQUIRE_FALSE(q.get_encrypted().empty());
     194           1 :         f.save("user", q);
     195           1 :     }
     196           1 :     CATCH_END_SECTION()
     197           1 : }
     198             : 
     199             : 
     200           2 : CATCH_TEST_CASE("file_remove", "[file][save][load][remove]")
     201             : {
     202           2 :     CATCH_START_SECTION("file_remove: create file, close, re-load, remove, re-re-load, re-remove")
     203             :     {
     204           1 :         char const * user_names[] = {
     205             :             "charlie",
     206             :             "hubert",
     207             :             "julius",
     208             :             "pompom",
     209             :             "henri",
     210             :             "louis",
     211             :             "jesus",
     212             :         };
     213           1 :         std::string const filename(get_tmp_dir("removal.pwd"));
     214             : 
     215           1 :         std::vector<safepasswords::password> v;
     216             :         {
     217           1 :             safepasswords::file f(filename);
     218             : 
     219           8 :             for(std::size_t idx(0); idx < std::size(user_names); ++idx)
     220             :             {
     221           7 :                 safepasswords::password p;
     222           7 :                 p.generate(); // this regenerates a new password
     223           7 :                 CATCH_REQUIRE(f.save(user_names[idx], p));
     224           7 :                 v.push_back(p);
     225           7 :             }
     226           1 :         }
     227             : 
     228             :         {
     229           1 :             safepasswords::file f(filename);
     230             : 
     231           8 :             for(std::size_t idx(0); idx < std::size(user_names); ++idx)
     232             :             {
     233           7 :                 safepasswords::password p;
     234           7 :                 CATCH_REQUIRE(f.find(user_names[idx], p));
     235             : 
     236             :                 // make sure it did not change between the save + load
     237             :                 //
     238           7 :                 CATCH_REQUIRE(v[idx].get_digest() == p.get_digest());
     239           7 :                 CATCH_REQUIRE(v[idx].get_salt() == p.get_salt());
     240           7 :                 CATCH_REQUIRE(v[idx].get_encrypted() == p.get_encrypted());
     241             : 
     242             :                 // remove the odd ones
     243             :                 //
     244           7 :                 if((idx & 1) != 0)
     245             :                 {
     246           3 :                     CATCH_REQUIRE(f.remove(user_names[idx]));
     247             :                 }
     248           7 :             }
     249           1 :         }
     250             : 
     251             :         {
     252           1 :             safepasswords::file f(filename);
     253             : 
     254           8 :             for(std::size_t idx(0); idx < std::size(user_names); ++idx)
     255             :             {
     256           7 :                 safepasswords::password p;
     257           7 :                 if((idx & 1) != 0)
     258             :                 {
     259             :                     // this one was removed, so we won't find it
     260             :                     //
     261           3 :                     CATCH_REQUIRE_FALSE(f.find(user_names[idx], p));
     262             : 
     263             :                     // we can re-remove, nothing happens
     264             :                     //
     265           3 :                     CATCH_REQUIRE(f.remove(user_names[idx]));
     266             :                 }
     267             :                 else
     268             :                 {
     269           4 :                     CATCH_REQUIRE(f.find(user_names[idx], p));
     270             : 
     271             :                     // make sure it's still there
     272             :                     //
     273           4 :                     CATCH_REQUIRE(v[idx].get_digest() == p.get_digest());
     274           4 :                     CATCH_REQUIRE(v[idx].get_salt() == p.get_salt());
     275           4 :                     CATCH_REQUIRE(v[idx].get_encrypted() == p.get_encrypted());
     276             :                 }
     277           7 :             }
     278           1 :         }
     279             : 
     280           1 :     }
     281           2 :     CATCH_END_SECTION()
     282             : 
     283           2 :     CATCH_START_SECTION("file_remove: missing '\\n'")
     284             :     {
     285           1 :         std::string const filename(get_tmp_dir("missing-nl.pwd"));
     286             :         {
     287           1 :             std::ofstream out;
     288           1 :             out.open(filename);
     289           1 :             CATCH_REQUIRE(out.is_open());
     290             : 
     291             :             // valid entry
     292             :             //
     293             :             out << "correct:md5:"
     294           2 :                 << snapdev::bin_to_hex("salt--0123456789")
     295             :                 << ':'
     296           2 :                 << snapdev::bin_to_hex("entry for once")
     297           3 :                 << '\n';
     298             : 
     299             :             // invalid entry
     300             :             //
     301             :             out << "missing-nl:sha512:"     // missing '\n' at the end
     302           2 :                 << snapdev::bin_to_hex("even more salt!!")
     303             :                 << ':'
     304           2 :                 << snapdev::bin_to_hex("entry for once");
     305           1 :         }
     306             : 
     307             :         {
     308           1 :             safepasswords::file f(filename);
     309           1 :             safepasswords::password p;
     310             : 
     311           1 :             CATCH_REQUIRE(f.next(p) == "correct");
     312           1 :             CATCH_REQUIRE(f.next(p).empty()); // we already cannot load "missing-nl" in this case
     313             : 
     314           1 :             CATCH_REQUIRE(f.remove("missing-nl"));
     315           1 :         }
     316             : 
     317             :         {
     318           1 :             safepasswords::file f(filename);
     319           1 :             safepasswords::password p;
     320             : 
     321           1 :             CATCH_REQUIRE(f.next(p) == "correct");
     322           1 :             CATCH_REQUIRE(f.next(p).empty()); // so this tests nothing since it was already not loadable before the remove...
     323             : 
     324             :             // but I could verify by hand and it works...
     325             :             //
     326             :             // TODO:
     327             :             // what we would have to do is create a memory version of what
     328             :             // is expected in the file and reload with file_contents to
     329             :             // make sure it is equal to what's expected
     330           1 :         }
     331           1 :     }
     332           2 :     CATCH_END_SECTION()
     333           2 : }
     334             : 
     335             : 
     336           4 : CATCH_TEST_CASE("file_iterate", "[file][iterate][load]")
     337             : {
     338           4 :     CATCH_START_SECTION("file_iterate: create file, close, load, go through with next()")
     339             :     {
     340           1 :         char const * user_names[] = {
     341             :             "charlotte",
     342             :             "henriette",
     343             :             "julia",
     344             :             "ponpon",
     345             :             "theo",
     346             :             "louisa",
     347             :             "angel",
     348             :         };
     349           1 :         std::string const filename(get_tmp_dir("iterate.pwd"));
     350             : 
     351           1 :         std::vector<safepasswords::password> v;
     352             :         {
     353           1 :             safepasswords::file f(filename);
     354             : 
     355           8 :             for(std::size_t idx(0); idx < std::size(user_names); ++idx)
     356             :             {
     357           7 :                 safepasswords::password p;
     358           7 :                 p.generate(); // this regenerates a new password
     359           7 :                 CATCH_REQUIRE(f.save(user_names[idx], p));
     360           7 :                 v.push_back(p);
     361           7 :             }
     362           1 :         }
     363             : 
     364             :         {
     365           1 :             safepasswords::file f(filename);
     366             : 
     367           1 :             for(std::size_t idx(0);; ++idx)
     368             :             {
     369           8 :                 safepasswords::password p;
     370           8 :                 std::string const username(f.next(p));
     371           8 :                 if(username.empty())
     372             :                 {
     373           1 :                     std::string const still_empty(f.next(p));
     374           1 :                     CATCH_REQUIRE(still_empty.empty());
     375           1 :                     break;
     376           1 :                 }
     377             : 
     378             :                 // make sure it did not change between the save + load
     379             :                 //
     380           7 :                 CATCH_REQUIRE(idx < std::size(user_names));
     381           7 :                 CATCH_REQUIRE(username == user_names[idx]);
     382           7 :                 CATCH_REQUIRE(v[idx].get_digest() == p.get_digest());
     383           7 :                 CATCH_REQUIRE(v[idx].get_salt() == p.get_salt());
     384           7 :                 CATCH_REQUIRE(v[idx].get_encrypted() == p.get_encrypted());
     385          16 :             }
     386             : 
     387             :             // do it a second time after a rewind
     388             :             //
     389           1 :             f.rewind();
     390             : 
     391           1 :             for(std::size_t idx(0);; ++idx)
     392             :             {
     393           8 :                 safepasswords::password p;
     394           8 :                 std::string const username(f.next(p));
     395           8 :                 if(username.empty())
     396             :                 {
     397           1 :                     std::string const still_empty(f.next(p));
     398           1 :                     CATCH_REQUIRE(still_empty.empty());
     399           1 :                     break;
     400           1 :                 }
     401             : 
     402             :                 // make sure it did not change between the save + load
     403             :                 //
     404           7 :                 CATCH_REQUIRE(idx < std::size(user_names));
     405           7 :                 CATCH_REQUIRE(username == user_names[idx]);
     406           7 :                 CATCH_REQUIRE(v[idx].get_digest() == p.get_digest());
     407           7 :                 CATCH_REQUIRE(v[idx].get_salt() == p.get_salt());
     408           7 :                 CATCH_REQUIRE(v[idx].get_encrypted() == p.get_encrypted());
     409          16 :             }
     410           1 :         }
     411           1 :     }
     412           4 :     CATCH_END_SECTION()
     413             : 
     414           4 :     CATCH_START_SECTION("file_iterate: name not followed by ':'")
     415             :     {
     416           1 :         std::string const filename(get_tmp_dir("entries.pwd"));
     417             :         {
     418           1 :             std::ofstream out;
     419           1 :             out.open(filename);
     420           1 :             CATCH_REQUIRE(out.is_open());
     421             : 
     422             :             // valid entry
     423             :             //
     424             :             out << "valid:sha512:"
     425           2 :                 << snapdev::bin_to_hex("salt--0123456789")
     426             :                 << ':'
     427           2 :                 << snapdev::bin_to_hex("entry for once")
     428           3 :                 << '\n';
     429             : 
     430             :             // invalid entry
     431             :             //
     432             :             out << "without-digest"     // no ':' after user name
     433           1 :                 << '\n';
     434           1 :         }
     435           1 :         safepasswords::file f(filename);
     436           1 :         safepasswords::password p;
     437             : 
     438             :         // first is valid
     439             :         //
     440           1 :         CATCH_REQUIRE(f.next(p) == "valid");
     441           1 :         CATCH_REQUIRE(p.get_plain().empty());
     442           1 :         CATCH_REQUIRE(p.get_digest() == "sha512");
     443           1 :         CATCH_REQUIRE(p.get_salt() == "salt--0123456789");
     444           1 :         CATCH_REQUIRE(p.get_encrypted() == "entry for once");
     445             : 
     446           1 :         CATCH_REQUIRE(f.next(p).empty());
     447           1 :         CATCH_REQUIRE(p.get_plain().empty());
     448           1 :         CATCH_REQUIRE(p.get_digest() == "sha512");
     449           1 :         CATCH_REQUIRE(p.get_salt().empty());
     450           1 :     }
     451           4 :     CATCH_END_SECTION()
     452             : 
     453           4 :     CATCH_START_SECTION("file_iterate: empty name not valid")
     454             :     {
     455           1 :         std::string const filename(get_tmp_dir("entries.pwd"));
     456             :         {
     457           1 :             std::ofstream out;
     458           1 :             out.open(filename);
     459           1 :             CATCH_REQUIRE(out.is_open());
     460             : 
     461             :             // valid entry
     462             :             //
     463             :             out << "correct:md5:"
     464           2 :                 << snapdev::bin_to_hex("salt--0123456789")
     465             :                 << ':'
     466           2 :                 << snapdev::bin_to_hex("entry for once")
     467           3 :                 << '\n';
     468             : 
     469             :             // invalid entry
     470             :             //
     471             :             out << ":sha512:"     // no name before ':'
     472           2 :                 << snapdev::bin_to_hex("even more salt!!")
     473             :                 << ':'
     474           2 :                 << snapdev::bin_to_hex("name is missing")
     475           3 :                 << '\n';
     476           1 :         }
     477           1 :         safepasswords::file f(filename);
     478           1 :         safepasswords::password p;
     479             : 
     480             :         // first is valid
     481             :         //
     482           1 :         CATCH_REQUIRE(f.next(p) == "correct");
     483           1 :         CATCH_REQUIRE(p.get_plain().empty());
     484           1 :         CATCH_REQUIRE(p.get_digest() == "md5");
     485           1 :         CATCH_REQUIRE(p.get_salt() == "salt--0123456789");
     486           1 :         CATCH_REQUIRE(p.get_encrypted() == "entry for once");
     487             : 
     488           1 :         CATCH_REQUIRE(f.next(p).empty());
     489           1 :         CATCH_REQUIRE(p.get_plain().empty());
     490           1 :         CATCH_REQUIRE(p.get_digest() == "md5");
     491           1 :         CATCH_REQUIRE(p.get_salt().empty());
     492           1 :     }
     493           4 :     CATCH_END_SECTION()
     494             : 
     495           4 :     CATCH_START_SECTION("file_iterate: missing encrypted value")
     496             :     {
     497           1 :         std::string const filename(get_tmp_dir("entries.pwd"));
     498             :         {
     499           1 :             std::ofstream out;
     500           1 :             out.open(filename);
     501           1 :             CATCH_REQUIRE(out.is_open());
     502             : 
     503             :             // valid entry
     504             :             //
     505             :             out << "correct:md5:"
     506           2 :                 << snapdev::bin_to_hex("salt--0123456789")
     507             :                 << ':'
     508           2 :                 << snapdev::bin_to_hex("entry for once")
     509           3 :                 << '\n';
     510             : 
     511             :             // invalid entry
     512             :             //
     513             :             out << "missing-stuff:sha512:"     // missing encrypted value
     514           2 :                 << snapdev::bin_to_hex("even more salt!!")
     515           2 :                 << '\n';
     516           1 :         }
     517           1 :         safepasswords::file f(filename);
     518           1 :         safepasswords::password p;
     519             : 
     520             :         // first is valid
     521             :         //
     522           1 :         CATCH_REQUIRE(f.next(p) == "correct");
     523           1 :         CATCH_REQUIRE(p.get_plain().empty());
     524           1 :         CATCH_REQUIRE(p.get_digest() == "md5");
     525           1 :         CATCH_REQUIRE(p.get_salt() == "salt--0123456789");
     526           1 :         CATCH_REQUIRE(p.get_encrypted() == "entry for once");
     527             : 
     528           1 :         CATCH_REQUIRE(f.next(p).empty());
     529           1 :         CATCH_REQUIRE(p.get_plain().empty());
     530           1 :         CATCH_REQUIRE(p.get_digest() == "md5");
     531           1 :         CATCH_REQUIRE(p.get_salt().empty());
     532           1 :     }
     533           4 :     CATCH_END_SECTION()
     534           4 : }
     535             : 
     536             : 
     537           2 : CATCH_TEST_CASE("file_missing", "[file][load][save]")
     538             : {
     539           2 :     CATCH_START_SECTION("file_missing: attempt to load missing file, find fails")
     540             :     {
     541           2 :         safepasswords::file f(get_tmp_dir("missing.pwd"));
     542           1 :         safepasswords::password p;
     543           1 :         CATCH_REQUIRE_FALSE(f.find("anyone", p));
     544           1 :     }
     545           2 :     CATCH_END_SECTION()
     546             : 
     547           2 :     CATCH_START_SECTION("file_missing: attempt to load missing file, next fails")
     548             :     {
     549           2 :         safepasswords::file f(get_tmp_dir("missing.pwd"));
     550           1 :         safepasswords::password p;
     551           1 :         CATCH_REQUIRE(f.next(p).empty());
     552           1 :     }
     553           2 :     CATCH_END_SECTION()
     554           2 : }
     555             : 
     556             : 
     557           2 : CATCH_TEST_CASE("file_with_errors", "[file][error]")
     558             : {
     559           2 :     CATCH_START_SECTION("file_with_errors: verify invalid find() call")
     560             :     {
     561           2 :         safepasswords::file f(get_tmp_dir("ignore.pwd"));
     562           1 :         safepasswords::password p;
     563           3 :         CATCH_REQUIRE_THROWS_MATCHES(
     564             :                   f.find(std::string(), p)
     565             :                 , safepasswords::invalid_parameter
     566             :                 , Catch::Matchers::ExceptionMessage(
     567             :                           "safepasswords_exception: the file::find()/file::save()/file::remove() functions"
     568             :                           " cannot be called with an empty string in 'name'."));
     569           1 :     }
     570           2 :     CATCH_END_SECTION()
     571             : 
     572           2 :     CATCH_START_SECTION("file_with_errors: verify invalid save() call")
     573             :     {
     574           2 :         safepasswords::file f(get_tmp_dir("ignore.pwd"));
     575           1 :         safepasswords::password p;
     576           3 :         CATCH_REQUIRE_THROWS_MATCHES(
     577             :                   f.save(std::string(), p)
     578             :                 , safepasswords::invalid_parameter
     579             :                 , Catch::Matchers::ExceptionMessage(
     580             :                           "safepasswords_exception: the file::find()/file::save()/file::remove() functions"
     581             :                           " cannot be called with an empty string in 'name'."));
     582           1 :     }
     583           2 :     CATCH_END_SECTION()
     584           2 : }
     585             : 
     586             : 
     587             : 
     588             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14