blob: b8f788f841612830c5f4ea18396b7ce3bed59985 [file] [log] [blame]
/** @file
ts::file unit tests.
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <iostream>
#include <fstream> /* ofstream */
#include "tscore/ts_file.h"
#include "../../../tests/include/catch.hpp"
using ts::file::path;
// --------------------
TEST_CASE("ts_file", "[libts][ts_file]")
{
path p1("/home");
REQUIRE(p1.string() == "/home");
auto p2 = p1 / "bob";
REQUIRE(p2.string() == "/home/bob");
p2 = p2 / "git/ats/";
REQUIRE(p2.string() == "/home/bob/git/ats/");
p2 /= "lib/ts";
REQUIRE(p2.string() == "/home/bob/git/ats/lib/ts");
p2 /= "/home/dave";
REQUIRE(p2.string() == "/home/dave");
path p3 = path("/home/dave") / "git/tools";
REQUIRE(p3.string() == "/home/dave/git/tools");
}
TEST_CASE("ts_file_io", "[libts][ts_file_io]")
{
path file("/etc/hosts");
std::error_code ec;
std::string content = ts::file::load(file, ec);
REQUIRE(ec.value() == 0);
REQUIRE(content.size() > 0);
REQUIRE(content.find("localhost") != content.npos);
// Check some file properties.
REQUIRE(ts::file::is_readable(file) == true);
auto fs = ts::file::status(file, ec);
REQUIRE(ec.value() == 0);
REQUIRE(ts::file::is_dir(fs) == false);
REQUIRE(ts::file::is_regular_file(fs) == true);
// Failure case.
file = "unit-tests/no_such_file.txt";
content = ts::file::load(file, ec);
REQUIRE(ec.value() == 2);
REQUIRE(ts::file::is_readable(file) == false);
}
TEST_CASE("ts_file::path::parent_path", "[libts][fs_file]")
{
CHECK(ts::file::path("/").parent_path() == path("/"));
CHECK(ts::file::path("/absolute/path/file.txt").parent_path() == ts::file::path("/absolute/path"));
CHECK(ts::file::path("/absolute/path/.").parent_path() == ts::file::path("/absolute/path"));
CHECK(ts::file::path("relative/path/file.txt").parent_path() == ts::file::path("relative/path"));
CHECK(ts::file::path("relative/path/.").parent_path() == ts::file::path("relative/path"));
CHECK(ts::file::path(".").parent_path() == ts::file::path(""));
}
static std::string
setenvvar(const std::string &name, const std::string &value)
{
std::string saved;
if (nullptr != getenv(name.c_str())) {
saved.assign(value);
}
if (!value.empty()) {
setenv(name.c_str(), value.c_str(), 1);
} else {
unsetenv(name.c_str());
}
return saved;
}
TEST_CASE("ts_file::path::temp_directory_path", "[libts][fs_file]")
{
// Clean all temp dir env variables.
std::string s1 = setenvvar("TMPDIR", std::string());
std::string s2 = setenvvar("TEMPDIR", std::string());
std::string s3 = setenvvar("TMP", std::string());
std::string s;
// If nothing defined return "/tmp"
CHECK(ts::file::temp_directory_path() == ts::file::path("/tmp"));
// TMPDIR defined.
s = setenvvar("TMPDIR", "/temp_dirname1");
CHECK(ts::file::temp_directory_path() == ts::file::path("/temp_dirname1"));
setenvvar("TMPDIR", s);
// TEMPDIR
s = setenvvar("TEMPDIR", "/temp_dirname");
CHECK(ts::file::temp_directory_path() == ts::file::path("/temp_dirname"));
// TMP defined, it should take precedence over TEMPDIR.
s = setenvvar("TMP", "/temp_dirname1");
CHECK(ts::file::temp_directory_path() == ts::file::path("/temp_dirname1"));
// TMPDIR defined, it should take precedence over TMP.
s = setenvvar("TMPDIR", "/temp_dirname2");
CHECK(ts::file::temp_directory_path() == ts::file::path("/temp_dirname2"));
setenvvar("TMPDIR", s);
setenvvar("TMP", s);
setenvvar("TEMPDIR", s);
// Restore all temp dir env variables to their previous state.
setenvvar("TMPDIR", s1);
setenvvar("TEMPDIR", s2);
setenvvar("TMP", s3);
}
TEST_CASE("ts_file::path::create_directories", "[libts][fs_file]")
{
std::error_code ec;
path tempdir = ts::file::temp_directory_path();
CHECK_FALSE(ts::file::create_directories(path(), ec));
CHECK(ec.value() == EINVAL);
path testdir1 = tempdir / "dir1";
CHECK(ts::file::create_directories(testdir1, ec));
CHECK(ts::file::exists(testdir1));
path testdir2 = testdir1 / "dir2";
CHECK(ts::file::create_directories(testdir1, ec));
CHECK(ts::file::exists(testdir1));
// Cleanup
CHECK(ts::file::remove(testdir1, ec));
CHECK_FALSE(ts::file::exists(testdir1));
}
TEST_CASE("ts_file::path::remove", "[libts][fs_file]")
{
std::error_code ec;
path tempdir = ts::file::temp_directory_path();
CHECK_FALSE(ts::file::remove(path(), ec));
CHECK(ec.value() == EINVAL);
path testdir1 = tempdir / "dir1";
path testdir2 = testdir1 / "dir2";
path file1 = testdir2 / "test.txt";
// Simple creation and removal of a directory /tmp/dir1
CHECK(ts::file::create_directories(testdir1, ec));
CHECK(ts::file::exists(testdir1));
CHECK(ts::file::remove(testdir1, ec));
CHECK_FALSE(ts::file::exists(testdir1));
// Create /tmp/dir1/dir2 and remove /tmp/dir1/dir2 => /tmp/dir1 should exist
CHECK(ts::file::create_directories(testdir2, ec));
CHECK(ts::file::remove(testdir2, ec));
CHECK(ts::file::exists(testdir1));
// Create a file, remove it, test if exists and then attempting to remove it again should fail.
CHECK(ts::file::create_directories(testdir2, ec));
std::ofstream file(file1.string());
file << "Simple test file";
file.close();
CHECK(ts::file::exists(file1));
CHECK(ts::file::remove(file1, ec));
CHECK_FALSE(ts::file::exists(file1));
CHECK_FALSE(ts::file::remove(file1, ec));
// Clean up.
CHECK(ts::file::remove(testdir1, ec));
CHECK_FALSE(ts::file::exists(testdir1));
}
TEST_CASE("ts_file::path::canonical", "[libts][fs_file]")
{
std::error_code ec;
path tempdir = ts::file::canonical(ts::file::temp_directory_path(), ec);
path testdir1 = tempdir / "dir1";
path testdir2 = testdir1 / "dir2";
path testdir3 = testdir2 / "dir3";
path unorthodox = testdir3 / path("..") / path("..") / "dir2";
// Invalid empty path.
CHECK(path() == ts::file::canonical(path(), ec));
CHECK(ec.value() == EINVAL);
// Fail if directory does not exist
CHECK(path() == ts::file::canonical(unorthodox, ec));
CHECK(ec.value() == ENOENT);
// Create the dir3 and test again
CHECK(create_directories(testdir3, ec));
CHECK(ts::file::exists(testdir3));
CHECK(ts::file::exists(testdir2));
CHECK(ts::file::exists(testdir1));
CHECK(ts::file::exists(unorthodox));
CHECK(ts::file::canonical(unorthodox, ec) == testdir2);
CHECK(ec.value() == 0);
// Cleanup
CHECK(ts::file::remove(testdir1, ec));
CHECK_FALSE(ts::file::exists(testdir1));
}
TEST_CASE("ts_file::path::filename", "[libts][fs_file]")
{
CHECK(ts::file::filename(path("/foo/bar.txt")) == path("bar.txt"));
CHECK(ts::file::filename(path("/foo/.bar")) == path(".bar"));
CHECK(ts::file::filename(path("/foo/bar")) == path("bar"));
CHECK(ts::file::filename(path("/foo/bar/")) == path(""));
CHECK(ts::file::filename(path("/foo/.")) == path("."));
CHECK(ts::file::filename(path("/foo/..")) == path(".."));
CHECK(ts::file::filename(path("/foo/../bar")) == path("bar"));
CHECK(ts::file::filename(path("/foo/../bar/")) == path(""));
CHECK(ts::file::filename(path(".")) == path("."));
CHECK(ts::file::filename(path("..")) == path(".."));
CHECK(ts::file::filename(path("/")) == path(""));
CHECK(ts::file::filename(path("//host")) == path("host"));
}
TEST_CASE("ts_file::path::copy", "[libts][fs_file]")
{
std::error_code ec;
path tempdir = ts::file::temp_directory_path();
path testdir1 = tempdir / "dir1";
path testdir2 = testdir1 / "dir2";
path file1 = testdir2 / "test1.txt";
path file2 = testdir2 / "test2.txt";
// Invalid empty path, both to and from parameters.
CHECK_FALSE(ts::file::copy(path(), path(), ec));
CHECK(ec.value() == EINVAL);
CHECK(ts::file::create_directories(testdir2, ec));
std::ofstream file(file1.string());
file << "Simple test file";
file.close();
CHECK(ts::file::exists(file1));
// Invalid empty path, now from parameter is ok but to is empty
CHECK_FALSE(ts::file::copy(file1, path(), ec));
CHECK(ec.value() == EINVAL);
// successfull copy: "to" is directory
CHECK(ts::file::copy(file1, testdir2, ec));
CHECK(ec.value() == 0);
// successful copy: "to" is file
CHECK(ts::file::copy(file1, file2, ec));
CHECK(ec.value() == 0);
// Compare the content
CHECK(ts::file::load(file1, ec) == ts::file::load(file2, ec));
// Cleanup
CHECK(ts::file::remove(testdir1, ec));
CHECK_FALSE(ts::file::exists(testdir1));
}