diff --git a/aegisub/build/tests/tests.vcxproj b/aegisub/build/tests/tests.vcxproj index ff4b5fdff..e4c401b99 100644 --- a/aegisub/build/tests/tests.vcxproj +++ b/aegisub/build/tests/tests.vcxproj @@ -42,6 +42,7 @@ + diff --git a/aegisub/build/tests/tests.vcxproj.filters b/aegisub/build/tests/tests.vcxproj.filters index ad542727b..559651e9d 100644 --- a/aegisub/build/tests/tests.vcxproj.filters +++ b/aegisub/build/tests/tests.vcxproj.filters @@ -29,6 +29,9 @@ Tests + + Tests + Tests diff --git a/aegisub/tests/Makefile b/aegisub/tests/Makefile index a62bb01d9..0f3ae6438 100644 --- a/aegisub/tests/Makefile +++ b/aegisub/tests/Makefile @@ -21,6 +21,7 @@ SRC = \ tests/cajun.cpp \ tests/color.cpp \ tests/dialogue_lexer.cpp \ + tests/fs.cpp \ tests/hotkey.cpp \ tests/iconv.cpp \ tests/ifind.cpp \ diff --git a/aegisub/tests/setup.bat b/aegisub/tests/setup.bat index 6e242c7fe..9886040e5 100644 --- a/aegisub/tests/setup.bat +++ b/aegisub/tests/setup.bat @@ -24,10 +24,17 @@ echo {"Valid" : ["Entry One", "Entry Two"]} > data/mru_ok.json echo {"Invalid" : [1, 3]} > data/mru_invalid.json -echo > data/rename_me +echo '1234567890' > data\ten_bytes +echo '' > data\touch_mod_time -echo > data/rename_me_overwrite -echo > data/rename_me_overwrite_renamed +mkdir data/options +cp options/* data/options + +mkdir data\dir_iterator +echo '' > data\dir_iterator\1.a +echo '' > data\dir_iterator\2.a +echo '' > data\dir_iterator\1.b +echo '' > data\dir_iterator\2.b mkdir data\options xcopy "%~dp0\options" data\options diff --git a/aegisub/tests/setup.sh b/aegisub/tests/setup.sh index 99b14ff7c..127ddb827 100755 --- a/aegisub/tests/setup.sh +++ b/aegisub/tests/setup.sh @@ -24,14 +24,18 @@ echo '{"Valid" : ["Entry One", "Entry Two"]}' > data/mru_ok.json echo '{"Invalid" : [1, 3]}' > data/mru_invalid.json -touch data/rename_me - -touch data/rename_me_overwrite -touch data/rename_me_overwrite_renamed +printf %s '1234567890' > data/ten_bytes +touch data/touch_mod_time mkdir data/options cp options/* data/options +mkdir data/dir_iterator +touch data/dir_iterator/1.a +touch data/dir_iterator/2.a +touch data/dir_iterator/1.b +touch data/dir_iterator/2.b + mkdir data/vfr mkdir data/vfr/in mkdir data/vfr/out diff --git a/aegisub/tests/support/main.cpp b/aegisub/tests/support/main.cpp index 3f0808246..8b86c29f8 100644 --- a/aegisub/tests/support/main.cpp +++ b/aegisub/tests/support/main.cpp @@ -19,6 +19,8 @@ #include #include +#include +#include int main(int argc, char **argv) { agi::dispatch::Init([](agi::dispatch::Thunk f) { }); @@ -29,6 +31,8 @@ int main(int argc, char **argv) { agi::log::log->Subscribe(new agi::log::JsonEmitter("./")); ::testing::InitGoogleTest(&argc, argv); + srand(time(nullptr)); + retval = RUN_ALL_TESTS(); delete agi::log::log; diff --git a/aegisub/tests/support/util.cpp b/aegisub/tests/support/util.cpp index 6061081d7..532ce9be2 100644 --- a/aegisub/tests/support/util.cpp +++ b/aegisub/tests/support/util.cpp @@ -16,6 +16,7 @@ #include "util.h" +#include #include #include @@ -28,4 +29,18 @@ bool compare(const std::string &file1, const std::string &file2) { return ss1.str() == ss2.str(); } +int write_rand(const char *path) { + int value = rand(); + std::ofstream of(path); + of << value; + return value; +} + +int read_written_rand(const char *path) { + int value; + std::ifstream i(path); + i >> value; + return value; +} + } diff --git a/aegisub/tests/support/util.h b/aegisub/tests/support/util.h index 738b12ecb..d95491eec 100644 --- a/aegisub/tests/support/util.h +++ b/aegisub/tests/support/util.h @@ -35,4 +35,7 @@ static std::vector make_vector(int len, ...) { return vec; } +int write_rand(const char *path); +int read_written_rand(const char *path); + } diff --git a/aegisub/tests/tests/fs.cpp b/aegisub/tests/tests/fs.cpp new file mode 100644 index 000000000..84073f9b6 --- /dev/null +++ b/aegisub/tests/tests/fs.cpp @@ -0,0 +1,197 @@ +// Copyright (c) 2013, Thomas Goyne +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// Aegisub Project http://www.aegisub.org/ + +#include "main.h" +#include "util.h" + +#include + +using namespace agi::fs; + +TEST(lagi_fs, exists) { + EXPECT_TRUE(Exists("data/file")); + EXPECT_TRUE(Exists("data/dir")); + EXPECT_FALSE(Exists("data/nonexistent")); +} + +TEST(lagi_fs, exists_does_not_throw) { + EXPECT_NO_THROW(Exists("data/file")); + EXPECT_NO_THROW(Exists("data/dir")); + EXPECT_NO_THROW(Exists("data/nonexistent")); + EXPECT_NO_THROW(Exists("data/dir_access_denied")); + EXPECT_NO_THROW(Exists("data/file_access_denied")); + EXPECT_NO_THROW(Exists("schema://host/file")); +} + +TEST(lagi_fs, file_exists) { + EXPECT_TRUE(FileExists("data/file")); + EXPECT_FALSE(FileExists("data/dir")); +} + +TEST(lagi_fs, dir_exists) { + EXPECT_FALSE(DirectoryExists("data/file")); + EXPECT_TRUE(DirectoryExists("data/dir")); +} + +#ifdef _WIN32 +#else +TEST(lagi_fs, short_name_is_a_no_op) { + EXPECT_STREQ("a b c d", ShortName("a b c d").c_str()); +} +#endif + +TEST(lagi_fs, free_space_returns_a_value) { + uintmax_t space = 0; + ASSERT_NO_THROW(space = FreeSpace(".")); + EXPECT_LT(0, space); +} + +TEST(lagi_fs, file_size) { + EXPECT_EQ(0u, Size("data/file")); + EXPECT_EQ(10u, Size("data/ten_bytes")); + EXPECT_THROW(Size("data/dir"), NotAFile); +} + +TEST(lagi_fs, touch_creates_file) { + Remove("data/touch_tmp"); + ASSERT_FALSE(Exists("data/touch_tmp")); + Touch("data/touch_tmp"); + EXPECT_TRUE(Exists("data/touch_tmp")); + Remove("data/touch_tmp"); +} + +TEST(lagi_fs, touch_updates_modified_time) { + time_t mod_time = ModifiedTime("data/touch_mod_time"); + Touch("data/touch_mod_time"); + EXPECT_LT(mod_time, ModifiedTime("data/touch_mod_time")); +} + +TEST(lagi_fs, touch_does_not_modify_contents) { + int expected_value = util::write_rand("data/tmp"); + + Touch("data/tmp"); + + EXPECT_EQ(expected_value, util::read_written_rand("data/tmp")); +} + +TEST(lagi_fs, rename) { + ASSERT_NO_THROW(Touch("data/rename_in")); + ASSERT_NO_THROW(Remove("data/rename_out")); + ASSERT_NO_THROW(Rename("data/rename_in", "data/rename_out")); + EXPECT_FALSE(FileExists("data/rename_in")); + EXPECT_TRUE(FileExists("data/rename_out")); +} + +TEST(lagi_fs, rename_overwrites) { + int expected_value = util::write_rand("data/rename_in"); + ASSERT_NO_THROW(Remove("data/rename_out")); + ASSERT_NO_THROW(Touch("data/rename_out")); + + ASSERT_NO_THROW(Rename("data/rename_in", "data/rename_out")); + + EXPECT_FALSE(FileExists("data/rename_in")); + EXPECT_TRUE(FileExists("data/rename_out")); + EXPECT_EQ(expected_value, util::read_written_rand("data/rename_out")); +} + +TEST(lagi_fs, copy) { + int expected_value = util::write_rand("data/copy_in"); + ASSERT_NO_THROW(Remove("data/copy_out")); + + ASSERT_NO_THROW(Copy("data/copy_in", "data/copy_out")); + + EXPECT_TRUE(FileExists("data/copy_in")); + EXPECT_TRUE(FileExists("data/copy_out")); + EXPECT_EQ(expected_value, util::read_written_rand("data/copy_out")); +} + +TEST(lagi_fs, copy_overwrites) { + int expected_value = util::write_rand("data/copy_in"); + ASSERT_NO_THROW(Remove("data/copy_out")); + ASSERT_NO_THROW(Touch("data/copy_out")); + + ASSERT_NO_THROW(Copy("data/copy_in", "data/copy_out")); + + EXPECT_TRUE(FileExists("data/copy_in")); + EXPECT_TRUE(FileExists("data/copy_out")); + EXPECT_EQ(expected_value, util::read_written_rand("data/copy_out")); +} + +TEST(lagi_fs, copy_creates_path) { +} + +TEST(lagi_fs, has_extension) { + EXPECT_TRUE(HasExtension("foo.txt", "txt")); + EXPECT_TRUE(HasExtension("foo.TXT", "txt")); + EXPECT_TRUE(HasExtension("foo.tar.gz", "gz")); + EXPECT_TRUE(HasExtension("foo.tar.gz", "tar.gz")); + EXPECT_TRUE(HasExtension("foo.\xC3\x9F", "\xC3\x9F")); // sharp s + + EXPECT_FALSE(HasExtension("foo.tx", "txt")); + EXPECT_FALSE(HasExtension("footxt", "txt")); + EXPECT_FALSE(HasExtension("foo.txt/", "txt")); + EXPECT_FALSE(HasExtension("foo.tar.gz", "tar")); +} + +TEST(lagi_fs, dir_iterator_bad_directory) { + std::vector files; + ASSERT_NO_THROW(DirectoryIterator("data/nonexistent", "*.*").GetAll(files)); + EXPECT_TRUE(files.empty()); +} + +TEST(lagi_fs, dir_iterator_no_filter) { + std::vector files; + ASSERT_NO_THROW(DirectoryIterator("data/dir_iterator", "").GetAll(files)); + ASSERT_EQ(4u, files.size()); + sort(begin(files), end(files)); // order is not guaranteed + EXPECT_STREQ("1.a", files[0].c_str()); + EXPECT_STREQ("1.b", files[1].c_str()); + EXPECT_STREQ("2.a", files[2].c_str()); + EXPECT_STREQ("2.b", files[3].c_str()); +} + +TEST(lagi_fs, dir_iterator_ext_filter) { + std::vector files; + ASSERT_NO_THROW(DirectoryIterator("data/dir_iterator", "*.a").GetAll(files)); + ASSERT_EQ(2u, files.size()); + sort(begin(files), end(files)); // order is not guaranteed + EXPECT_STREQ("1.a", files[0].c_str()); + EXPECT_STREQ("2.a", files[1].c_str()); +} + +TEST(lagi_fs, dir_iterator_ext_filter_skipping_first_works) { + std::vector files; + ASSERT_NO_THROW(DirectoryIterator("data/dir_iterator", "*.b").GetAll(files)); + ASSERT_EQ(2u, files.size()); + sort(begin(files), end(files)); // order is not guaranteed + EXPECT_STREQ("1.b", files[0].c_str()); + EXPECT_STREQ("2.b", files[1].c_str()); +} + +TEST(lagi_fs, dir_iterator_fn_filter) { + std::vector files; + ASSERT_NO_THROW(DirectoryIterator("data/dir_iterator", "1.*").GetAll(files)); + ASSERT_EQ(2u, files.size()); + sort(begin(files), end(files)); // order is not guaranteed + EXPECT_STREQ("1.a", files[0].c_str()); + EXPECT_STREQ("1.b", files[1].c_str()); +} + +TEST(lagi_fs, dir_iterator_all_filtered_out) { + std::vector files; + ASSERT_NO_THROW(DirectoryIterator("data/dir_iterator", "*.c").GetAll(files)); + EXPECT_TRUE(files.empty()); +} diff --git a/aegisub/tests/tests/ifind.cpp b/aegisub/tests/tests/ifind.cpp index baad59913..8c0b75656 100644 --- a/aegisub/tests/tests/ifind.cpp +++ b/aegisub/tests/tests/ifind.cpp @@ -14,6 +14,8 @@ // // Aegisub Project http://www.aegisub.org/ +#include "../../libaegisub/config.h" + #include #include "main.h" diff --git a/aegisub/tests/tests/path.cpp b/aegisub/tests/tests/path.cpp index b20a9e66d..ce93c76e9 100644 --- a/aegisub/tests/tests/path.cpp +++ b/aegisub/tests/tests/path.cpp @@ -130,3 +130,43 @@ TEST(lagi_path, platform_paths_have_values_and_exist) { TEST_PLATFORM_PATH_TOKEN("?local"); TEST_PLATFORM_PATH_TOKEN("?temp"); } + +TEST(lagi_path, making_empty_absolute_gives_empty) { + Path p; + ASSERT_NO_THROW(p.MakeAbsolute("", "?data")); + EXPECT_TRUE(p.MakeAbsolute("", "?data").empty()); +} + +TEST(lagi_path, making_empty_relative_gives_empty) { + Path p; + ASSERT_NO_THROW(p.MakeRelative("", "?data")); + EXPECT_TRUE(p.MakeRelative("", "?data").empty()); +} + +#ifdef _WIN32 +TEST(lagi_path, make_absolute_on_network_path) { + Path p; + ASSERT_NO_THROW(p.MakeAbsolute("//foo/bar", "?data")); + EXPECT_STREQ("\\\\foo\\bar", p.MakeAbsolute("//foo/bar", "?data").string().c_str()); +} + +TEST(lagi_path, make_relative_on_network_path) { + Path p; + ASSERT_NO_THROW(p.MakeRelative("\\\\foo\\bar", "?data")); + EXPECT_STREQ("\\\\foo\\bar", p.MakeRelative("\\\\foo\\bar", "?data").string().c_str()); +} +#endif + +#define EXPECT_UNCHANGED(url, func) EXPECT_STREQ(url, p.func(url, "?data").string().c_str()) + +TEST(lagi_path, make_absolute_on_dummy_url) { + Path p; + EXPECT_UNCHANGED("dummy-audio:silence?sr=44100&bd=16&ch=1&ln=396900000", MakeAbsolute); + EXPECT_UNCHANGED("?dummy:23.976000:40000:1280:720:47:163:254:", MakeAbsolute); +} + +TEST(lagi_path, make_relative_on_dummy_url) { + Path p; + EXPECT_UNCHANGED("dummy-audio:silence?sr=44100&bd=16&ch=1&ln=396900000", MakeRelative); + EXPECT_UNCHANGED("?dummy:23.976000:40000:1280:720:47:163:254:", MakeRelative); +}