The Battle for Wesnoth  1.17.0-dev
test_filesystem.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2015 - 2021
3  by Iris Morelle <shadowm2006@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
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 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #include <boost/test/unit_test.hpp>
17 #include "filesystem.hpp"
18 #include "game_config.hpp"
19 
20 #if 0
21 namespace {
22 
23 template<typename T>
24 void dump(const T& v)
25 {
26  for(typename T::const_iterator k = v.begin(); k != v.end(); ++k) {
27  std::cerr << " * " << *k << '\n';
28  }
29 }
30 
31 }
32 #endif
33 
34 BOOST_AUTO_TEST_SUITE( filesystem ); // implicit namespace filesystem
35 
36 const std::string& gamedata = game_config::path;
37 
38 BOOST_AUTO_TEST_CASE( test_fs_game_path_reverse_engineering )
39 {
40  const std::string maincfg = "_main.cfg";
41 
42  std::string gamedata_rev = get_wml_location("_main.cfg");
43 
44  const std::size_t strip_len = (maincfg + "/data/").length();
45  BOOST_REQUIRE(gamedata_rev.length() > strip_len);
46  gamedata_rev.resize(gamedata_rev.length() - strip_len);
47 
48  BOOST_CHECK_EQUAL( gamedata_rev, gamedata );
49 }
50 
51 BOOST_AUTO_TEST_CASE( test_fs_base )
52 {
53  BOOST_CHECK( is_root("/") );
54  BOOST_CHECK( is_root("////") );
55  BOOST_CHECK( is_root("/../") );
56  BOOST_CHECK( is_root("/../.././") );
57  BOOST_CHECK( is_root("/.././../.") );
58  BOOST_CHECK( is_root("/.") );
59 
60  BOOST_CHECK( is_relative(".") );
61  BOOST_CHECK( is_relative("..") );
62  BOOST_CHECK( is_relative("../foo") );
63  BOOST_CHECK( is_relative("foo") );
64  BOOST_CHECK( !is_relative("/./../foo/..") );
65  BOOST_CHECK( !is_relative("/foo/..") );
66  BOOST_CHECK( !is_relative("/foo") );
67  BOOST_CHECK( !is_relative("///foo") );
68 
69  BOOST_CHECK( is_directory("/") );
70  BOOST_CHECK( is_directory("/.") );
71  BOOST_CHECK( is_directory("/./././.") );
72  BOOST_CHECK( is_directory("/..") );
73 
74  BOOST_CHECK( is_directory(".") );
75  BOOST_CHECK( is_directory("..") );
76  BOOST_CHECK( is_directory("./././.") );
77 
78  BOOST_CHECK( is_directory(gamedata + "/data/core/../../data/././../data/././core") );
79 
80  BOOST_CHECK( file_exists("/") );
81  BOOST_CHECK( file_exists("/.") );
82  BOOST_CHECK( file_exists("/./././.") );
83  BOOST_CHECK( file_exists("/..") );
84 
85  BOOST_CHECK_EQUAL( base_name("foo/bar/baz.cfg"), "baz.cfg" );
86  // FIXME: BFS gives "." for this, Unix basename gives "bar"!
87  //BOOST_CHECK_EQUAL( base_name("foo/bar/"), "bar" );
88  BOOST_CHECK_EQUAL( base_name("foo/bar"), "bar" );
89  BOOST_CHECK_EQUAL( base_name("/"), "/" );
90  BOOST_CHECK_EQUAL( base_name(""), "" );
91 
92  BOOST_CHECK_EQUAL( directory_name("foo/bar/baz.cfg"), "foo/bar" );
93  BOOST_CHECK_EQUAL( directory_name("foo/bar/"), "foo/bar" );
94  BOOST_CHECK_EQUAL( directory_name("foo/bar"), "foo" );
95  BOOST_CHECK_EQUAL( directory_name("/"), "" );
96  BOOST_CHECK_EQUAL( directory_name(""), "" );
97 
98  // TODO normalize_path
99 
100  //BOOST_CHECK_EQUAL( normalize_path(gamedata + "/data/core/../../data/././../data/././core"),
101  // gamedata + "/data/core" );
102 }
103 
104 BOOST_AUTO_TEST_CASE( test_fs_enum )
105 {
106  const std::string path = "data/test/test/filesystem/enum";
107 
108  const std::vector<std::string> expected_filenames {
109  "_initial.cfg",
110  "A1.cfg",
111  "A2.cfg",
112  "A3.cfg",
113  "B1.cfg",
114  "B2.cfg",
115  "B3.cfg",
116  "_final.cfg"};
117  const std::vector<std::string> expected_dirnames {
118  "D1",
119  "D2",
120  "D3"};
121 
122  std::vector<std::string> files, dirs;
123  std::vector<std::string> expected_filepaths, expected_dirpaths;
124 
125  for(const std::string& n : expected_filenames) {
126  expected_filepaths.push_back(gamedata + "/" + path + "/" + n);
127  }
128 
129  for(const std::string& n : expected_dirnames) {
130  expected_dirpaths.push_back(gamedata + "/" + path + "/" + n);
131  }
132 
133  // FIXME: get_files_in_dir with mode == FILE_NAME_ONLY will fail to reorder
134  // entries because the sorting code looks for forward slashes.
135  // This affects both the BFS-based and legacy implementations.
136  get_files_in_dir(path, &files, &dirs, name_mode::ENTIRE_FILE_PATH, filter_mode::NO_FILTER, reorder_mode::DO_REORDER);
137 
138  BOOST_CHECK( files == expected_filepaths );
139  BOOST_CHECK( dirs == expected_dirpaths );
140 }
141 
142 BOOST_AUTO_TEST_CASE( test_fs_binary_path )
143 {
144  BOOST_CHECK_EQUAL( get_binary_dir_location("images", "."), gamedata + "/images/." );
145 
146  // This test depends on get_binary_file_location() deterministically choosing
147  // which order to search the [binary_path] entries, as there are four "images"
148  // directories that could match.
149  BOOST_CHECK_EQUAL( get_binary_file_location("images", "././././././"),
150  gamedata + "/images/././././././" );
151 
152  BOOST_CHECK_EQUAL( get_binary_file_location("images", "wesnoth-icon.png"),
153  gamedata + "/data/core/images/wesnoth-icon.png" );
154 
155  BOOST_CHECK_EQUAL( get_binary_file_location("music", "silence.ogg"),
156  gamedata + "/data/core/music/silence.ogg" );
157 
158  BOOST_CHECK_EQUAL( get_binary_file_location("sounds", "explosion.ogg"),
159  gamedata + "/data/core/sounds/explosion.ogg" );
160 
161  BOOST_CHECK_EQUAL( get_independent_binary_file_path("images", "wesnoth-icon.png"),
162  "data/core/images/wesnoth-icon.png" );
163 
164  // Inexistent paths are resolved empty.
165  BOOST_CHECK( get_binary_dir_location("images", "").empty() );
166  BOOST_CHECK( get_binary_dir_location("inexistent_resource_type", "").empty() );
167  BOOST_CHECK( get_binary_file_location("image", "wesnoth-icon.png").empty() );
168  BOOST_CHECK( get_binary_file_location("images", "bunnies_and_ponies_and_rainbows_oh_em_gee.psd").empty() );
169  BOOST_CHECK( get_binary_file_location("music", "this_track_does_not_exist.aiff").empty() );
170  BOOST_CHECK( get_binary_file_location("sounds", "rude_noises.aiff").empty() );
171  BOOST_CHECK( get_independent_binary_file_path("images", "dopefish.txt").empty() );
172 }
173 
174 BOOST_AUTO_TEST_CASE( test_fs_wml_path )
175 {
176  const std::string& userdata = get_user_data_dir();
177 
178  BOOST_CHECK_EQUAL( get_wml_location(""), "" );
179 
180  BOOST_CHECK_EQUAL( get_wml_location("_main.cfg"), gamedata + "/data/_main.cfg" );
181  BOOST_CHECK_EQUAL( get_wml_location("core/_main.cfg"), gamedata + "/data/core/_main.cfg" );
182  BOOST_CHECK_EQUAL( get_wml_location("."), gamedata + "/data/." );
183 
184  BOOST_CHECK_EQUAL( get_wml_location("~/"), userdata + "/data/" );
185 
186  // Inexistent paths are resolved empty.
187  BOOST_CHECK( get_wml_location("why_would_anyone_ever_name_a_file_like_this").empty() );
188 }
189 
190 BOOST_AUTO_TEST_CASE( test_fs_search )
191 {
192  const std::string& userdata = get_user_data_dir();
193 
194  BOOST_CHECK_EQUAL( nearest_extant_parent(userdata + "/THIS_DOES_NOT_EXIST/foo/bar"), userdata );
195 
196  BOOST_CHECK_EQUAL( nearest_extant_parent(gamedata + "/THIS_DOES_NOT_EXIST_EITHER/foo"), gamedata );
197  BOOST_CHECK_EQUAL( nearest_extant_parent(gamedata + "/data/_main.cfg"), gamedata + "/data" );
198  BOOST_CHECK_EQUAL( nearest_extant_parent(gamedata + "/data/core/THIS_DOES_NOT_EXIST/test"), gamedata + "/data/core" );
199 
200  BOOST_CHECK_EQUAL( nearest_extant_parent("/THIS_HOPEFULLY_DOES_NOT_EXIST"), "/" );
201  BOOST_CHECK_EQUAL( nearest_extant_parent("/THIS_HOPEFULLY_DOES_NOT_EXIST/foo/bar"), "/" );
202  BOOST_CHECK_EQUAL( nearest_extant_parent("/THIS_HOPEFULLY_DOES_NOT_EXIST/foo/bar/.."), "/" );
203 }
204 
205 BOOST_AUTO_TEST_CASE( test_fs_fluff )
206 {
207  BOOST_CHECK( ends_with("foobarbazbat", "bazbat") );
208 
209  BOOST_CHECK( looks_like_pbl("foo.pbl") );
210  BOOST_CHECK( looks_like_pbl("FOO.PBL") );
211  BOOST_CHECK( looks_like_pbl("Foo.Pbl") );
212  BOOST_CHECK( !looks_like_pbl("foo.pbl.cfg") );
213 
214  BOOST_CHECK( is_gzip_file("foo.gz") );
215  BOOST_CHECK( !is_gzip_file("foo.gz.bz2") );
216  BOOST_CHECK( is_bzip2_file("foo.bz2") );
217  BOOST_CHECK( !is_bzip2_file("foo.bz2.gz") );
218 
219  BOOST_CHECK( is_compressed_file("foo.gz") );
220  BOOST_CHECK( is_compressed_file("foo.bz2") );
221  BOOST_CHECK( !is_compressed_file("foo.txt") );
222 
223  // FIXME: Is this even intended?
224  BOOST_CHECK( !is_gzip_file("foo.GZ") );
225  BOOST_CHECK( !is_bzip2_file("foo.BZ2") );
226  BOOST_CHECK( !is_compressed_file("foo.GZ") );
227  BOOST_CHECK( !is_compressed_file("foo.BZ2") );
228 }
229 
230 BOOST_AUTO_TEST_SUITE_END()
std::string get_binary_dir_location(const std::string &type, const std::string &filename)
Returns a complete path to the actual directory of a given type or an empty string if the directory i...
bool looks_like_pbl(const std::string &file)
static bool file_exists(const bfs::path &fpath)
Definition: filesystem.cpp:263
bool ends_with(const std::string &str, const std::string &suffix)
const std::string & gamedata
std::string get_binary_file_location(const std::string &type, const std::string &filename)
Returns a complete path to the actual file of a given type or an empty string if the file isn&#39;t prese...
std::string get_independent_binary_file_path(const std::string &type, const std::string &filename)
Returns an asset path to filename for binary path-independent use in saved games. ...
BOOST_AUTO_TEST_SUITE(filesystem)
std::string get_user_data_dir()
Definition: filesystem.cpp:792
void get_files_in_dir(const std::string &dir, std::vector< std::string > *files, std::vector< std::string > *dirs, name_mode mode, filter_mode filter, reorder_mode reorder, file_tree_checksum *checksum)
Get a list of all files and/or directories in a given directory.
Definition: filesystem.cpp:349
std::string nearest_extant_parent(const std::string &file)
Finds the nearest parent in existence for a file or directory.
bool is_directory(const std::string &fname)
Returns true if the given file is a directory.
std::string path
Definition: game_config.cpp:39
BOOST_AUTO_TEST_CASE(test_fs_game_path_reverse_engineering)
bool is_gzip_file(const std::string &filename)
Returns true if the file ends with &#39;.gz&#39;.
bool is_relative(const std::string &path)
Returns whether the path seems to be relative.
std::string get_wml_location(const std::string &filename, const std::string &current_dir)
Returns a complete path to the actual WML file or directory or an empty string if the file isn&#39;t pres...
bool is_compressed_file(const std::string &filename)
Definition: filesystem.hpp:258
bool is_root(const std::string &path)
Returns whether the path is the root of the file hierarchy.
Declarations for File-IO.
std::string base_name(const std::string &file, const bool remove_extension)
Returns the base filename of a file, with directory name stripped.
bool is_bzip2_file(const std::string &filename)
Returns true if the file ends with &#39;.bz2&#39;.
static map_location::DIRECTION n
std::string directory_name(const std::string &file)
Returns the directory name of a file, with filename stripped.