LCOV - code coverage report
Current view: top level - src/test - fs_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 111 111 100.0 %
Date: 2026-06-25 07:23:43 Functions: 38 38 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2011-2021 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : //
       5             : #include <fs.h>
       6             : #include <test/util/setup_common.h>
       7             : #include <util/getuniquepath.h>
       8             : #include <util/system.h>
       9             : 
      10             : #include <boost/test/unit_test.hpp>
      11             : 
      12             : #include <fstream>
      13             : #include <ios>
      14             : #include <string>
      15             : 
      16         146 : BOOST_FIXTURE_TEST_SUITE(fs_tests, BasicTestingSetup)
      17             : 
      18         149 : BOOST_AUTO_TEST_CASE(fsbridge_pathtostring)
      19             : {
      20           1 :     std::string u8_str = "fs_tests_∋_🏃";
      21           1 :     std::u8string str8{u8"fs_tests_∋_🏃"};
      22           1 :     BOOST_CHECK_EQUAL(fs::PathToString(fs::PathFromString(u8_str)), u8_str);
      23           1 :     BOOST_CHECK_EQUAL(fs::u8path(u8_str).utf8string(), u8_str);
      24           1 :     BOOST_CHECK_EQUAL(fs::path(str8).utf8string(), u8_str);
      25           1 :     BOOST_CHECK(fs::path(str8).u8string() == str8);
      26           1 :     BOOST_CHECK_EQUAL(fs::PathFromString(u8_str).utf8string(), u8_str);
      27           1 :     BOOST_CHECK_EQUAL(fs::PathToString(fs::u8path(u8_str)), u8_str);
      28             : #ifndef WIN32
      29             :     // On non-windows systems, verify that arbitrary byte strings containing
      30             :     // invalid UTF-8 can be round tripped successfully with PathToString and
      31             :     // PathFromString. On non-windows systems, paths are just byte strings so
      32             :     // these functions do not do any encoding. On windows, paths are Unicode,
      33             :     // and these functions do encoding and decoding, so the behavior of this
      34             :     // test would be undefined.
      35           1 :     std::string invalid_u8_str = "\xf0";
      36           1 :     BOOST_CHECK_EQUAL(invalid_u8_str.size(), 1);
      37           1 :     BOOST_CHECK_EQUAL(fs::PathToString(fs::PathFromString(invalid_u8_str)), invalid_u8_str);
      38             : #endif
      39           1 : }
      40             : 
      41         149 : BOOST_AUTO_TEST_CASE(fsbridge_stem)
      42             : {
      43           1 :     std::string test_filename = "fs_tests_∋_🏃.dat";
      44           1 :     std::string expected_stem = "fs_tests_∋_🏃";
      45           1 :     BOOST_CHECK_EQUAL(fs::PathToString(fs::PathFromString(test_filename).stem()), expected_stem);
      46           1 : }
      47             : 
      48         149 : BOOST_AUTO_TEST_CASE(fsbridge_fstream)
      49             : {
      50           1 :     fs::path tmpfolder = m_args.GetDataDirBase();
      51             :     // tmpfile1 should be the same as tmpfile2
      52           1 :     fs::path tmpfile1 = tmpfolder / fs::u8path("fs_tests_∋_🏃");
      53           1 :     fs::path tmpfile2 = tmpfolder / fs::path(u8"fs_tests_∋_🏃");
      54             :     {
      55           1 :         std::ofstream file{tmpfile1};
      56           1 :         file << "bitcoin";
      57           1 :     }
      58             :     {
      59           1 :         std::ifstream file{tmpfile2};
      60           1 :         std::string input_buffer;
      61           1 :         file >> input_buffer;
      62           1 :         BOOST_CHECK_EQUAL(input_buffer, "bitcoin");
      63           1 :     }
      64             :     {
      65           1 :         std::ifstream file{tmpfile1, std::ios_base::in | std::ios_base::ate};
      66           1 :         std::string input_buffer;
      67           1 :         file >> input_buffer;
      68           1 :         BOOST_CHECK_EQUAL(input_buffer, "");
      69           1 :     }
      70             :     {
      71           1 :         std::ofstream file{tmpfile2, std::ios_base::out | std::ios_base::app};
      72           1 :         file << "tests";
      73           1 :     }
      74             :     {
      75           1 :         std::ifstream file{tmpfile1};
      76           1 :         std::string input_buffer;
      77           1 :         file >> input_buffer;
      78           1 :         BOOST_CHECK_EQUAL(input_buffer, "bitcointests");
      79           1 :     }
      80             :     {
      81           1 :         std::ofstream file{tmpfile2, std::ios_base::out | std::ios_base::trunc};
      82           1 :         file << "bitcoin";
      83           1 :     }
      84             :     {
      85           1 :         std::ifstream file{tmpfile1};
      86           1 :         std::string input_buffer;
      87           1 :         file >> input_buffer;
      88           1 :         BOOST_CHECK_EQUAL(input_buffer, "bitcoin");
      89           1 :     }
      90             :     {
      91           1 :         fs::path p1 = GetUniquePath(tmpfolder);
      92           1 :         fs::path p2 = GetUniquePath(tmpfolder);
      93           1 :         fs::path p3 = GetUniquePath(tmpfolder);
      94             : 
      95             :         // Ensure that the parent path is always the same.
      96           1 :         BOOST_CHECK_EQUAL(tmpfolder, p1.parent_path());
      97           1 :         BOOST_CHECK_EQUAL(tmpfolder, p2.parent_path());
      98           1 :         BOOST_CHECK_EQUAL(tmpfolder, p3.parent_path());
      99             : 
     100             :         // Ensure that generated paths are actually different.
     101           1 :         BOOST_CHECK(p1 != p2);
     102           1 :         BOOST_CHECK(p2 != p3);
     103           1 :         BOOST_CHECK(p1 != p3);
     104           1 :     }
     105             :     {
     106             :         // Join an absolute path and a relative path.
     107           1 :         fs::path p = fsbridge::AbsPathJoin(tmpfolder, fs::u8path("fs_tests_∋_🏃"));
     108           1 :         BOOST_CHECK(p.is_absolute());
     109           1 :         BOOST_CHECK_EQUAL(tmpfile1, p);
     110           1 :     }
     111             :     {
     112             :         // Join two absolute paths.
     113           1 :         fs::path p = fsbridge::AbsPathJoin(tmpfile1, tmpfile2);
     114           1 :         BOOST_CHECK(p.is_absolute());
     115           1 :         BOOST_CHECK_EQUAL(tmpfile2, p);
     116           1 :     }
     117             :     {
     118             :         // Ensure joining with empty paths does not add trailing path components.
     119           1 :         BOOST_CHECK_EQUAL(tmpfile1, fsbridge::AbsPathJoin(tmpfile1, ""));
     120           1 :         BOOST_CHECK_EQUAL(tmpfile1, fsbridge::AbsPathJoin(tmpfile1, {}));
     121             :     }
     122           1 : }
     123             : 
     124         149 : BOOST_AUTO_TEST_CASE(rename)
     125             : {
     126           1 :     const fs::path tmpfolder{m_args.GetDataDirBase()};
     127             : 
     128           1 :     const fs::path path1{GetUniquePath(tmpfolder)};
     129           1 :     const fs::path path2{GetUniquePath(tmpfolder)};
     130             : 
     131           1 :     const std::string path1_contents{"1111"};
     132           1 :     const std::string path2_contents{"2222"};
     133             : 
     134             :     {
     135           1 :         std::ofstream file{path1};
     136           1 :         file << path1_contents;
     137           1 :     }
     138             : 
     139             :     {
     140           1 :         std::ofstream file{path2};
     141           1 :         file << path2_contents;
     142           1 :     }
     143             : 
     144             :     // Rename path1 -> path2.
     145           1 :     BOOST_CHECK(RenameOver(path1, path2));
     146             : 
     147           1 :     BOOST_CHECK(!fs::exists(path1));
     148             : 
     149             :     {
     150           1 :         std::ifstream file{path2};
     151           1 :         std::string contents;
     152           1 :         file >> contents;
     153           1 :         BOOST_CHECK_EQUAL(contents, path1_contents);
     154           1 :     }
     155           1 :     fs::remove(path2);
     156           1 : }
     157             : 
     158             : #ifndef __MINGW64__ // no symlinks on mingw
     159         149 : BOOST_AUTO_TEST_CASE(create_directories)
     160             : {
     161             :     // Test fs::create_directories workaround.
     162           1 :     const fs::path tmpfolder{m_args.GetDataDirBase()};
     163             : 
     164           1 :     const fs::path dir{GetUniquePath(tmpfolder)};
     165           1 :     fs::create_directory(dir);
     166           1 :     BOOST_CHECK(fs::exists(dir));
     167           1 :     BOOST_CHECK(fs::is_directory(dir));
     168           1 :     BOOST_CHECK(!fs::create_directories(dir));
     169             : 
     170           1 :     const fs::path symlink{GetUniquePath(tmpfolder)};
     171           1 :     fs::create_directory_symlink(dir, symlink);
     172           1 :     BOOST_CHECK(fs::exists(symlink));
     173           1 :     BOOST_CHECK(fs::is_symlink(symlink));
     174           1 :     BOOST_CHECK(fs::is_directory(symlink));
     175           1 :     BOOST_CHECK(!fs::create_directories(symlink));
     176             : 
     177           1 :     fs::remove(symlink);
     178           1 :     fs::remove(dir);
     179           1 : }
     180             : #endif // __MINGW64__
     181             : 
     182         146 : BOOST_AUTO_TEST_SUITE_END()
     183             : 

Generated by: LCOV version 1.16