blob: 452865b919c0d3644eb0ece0e17e402318aaff41 [file] [log] [blame]
// Licensed 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 <string>
#include <vector>
#include <gtest/gtest.h>
#include <stout/path.hpp>
#include <stout/os/exists.hpp>
#include <stout/os/getcwd.hpp>
#include <stout/os/int_fd.hpp>
#include <stout/os/open.hpp>
#include <stout/os/rm.hpp>
#include <stout/os/touch.hpp>
#include <stout/tests/utils.hpp>
using std::string;
using std::vector;
// Test many corner cases of Path::basename.
TEST(PathTest, Basename)
{
// Empty path check.
EXPECT_EQ(".", Path("").basename());
// Check common path patterns.
#ifdef __WINDOWS__
EXPECT_EQ("\\", Path("\\").basename());
#else
EXPECT_EQ("/", Path("/").basename());
#endif // __WINDOWS__
EXPECT_EQ(".", Path(".").basename());
EXPECT_EQ("..", Path("..").basename());
EXPECT_EQ("a", Path("a").basename());
#ifdef __WINDOWS__
EXPECT_EQ("b", Path("a\\b").basename());
EXPECT_EQ("c", Path("a\\b\\c").basename());
#else
EXPECT_EQ("b", Path("a/b").basename());
EXPECT_EQ("c", Path("a/b/c").basename());
#endif // __WINDOWS__
// Check leading slashes get cleaned up properly.
#ifdef __WINDOWS__
EXPECT_EQ("a", Path("\\a").basename());
EXPECT_EQ("a", Path("\\\\a").basename());
EXPECT_EQ("a", Path("\\a\\").basename());
EXPECT_EQ("c", Path("\\a\\b\\c").basename());
EXPECT_EQ("b", Path("\\a\\b").basename());
EXPECT_EQ("b", Path("\\\\a\\\\b").basename());
#else
EXPECT_EQ("a", Path("/a").basename());
EXPECT_EQ("a", Path("//a").basename());
EXPECT_EQ("a", Path("/a/").basename());
EXPECT_EQ("c", Path("/a/b/c").basename());
EXPECT_EQ("b", Path("/a/b").basename());
EXPECT_EQ("b", Path("//a//b").basename());
#endif // __WINDOWS__
// Check trailing slashes get cleaned up properly.
#ifdef __WINDOWS__
EXPECT_EQ("a", Path("a\\").basename());
EXPECT_EQ("c", Path("\\a\\b\\c\\\\").basename());
EXPECT_EQ("c", Path("\\a\\b\\c\\\\\\").basename());
EXPECT_EQ("\\", Path("\\\\").basename());
EXPECT_EQ("\\", Path("\\\\\\").basename());
#else
EXPECT_EQ("a", Path("a/").basename());
EXPECT_EQ("c", Path("/a/b/c//").basename());
EXPECT_EQ("c", Path("/a/b/c///").basename());
EXPECT_EQ("/", Path("//").basename());
EXPECT_EQ("/", Path("///").basename());
#endif // __WINDOWS__
}
// Test many corner cases of Path::dirname.
TEST(PathTest, Dirname)
{
// Empty path check.
EXPECT_EQ(".", Path("").dirname());
// Check common path patterns.
#ifdef __WINDOWS__
EXPECT_EQ("\\", Path("\\").dirname());
#else
EXPECT_EQ("/", Path("/").dirname());
#endif // __WINDOWS__
EXPECT_EQ(".", Path(".").dirname());
EXPECT_EQ(".", Path("..").dirname());
EXPECT_EQ(".", Path("a").dirname());
#ifdef __WINDOWS__
EXPECT_EQ("a", Path("a\\b").dirname());
EXPECT_EQ("a\\b", Path("a\\b\\c\\").dirname());
#else
EXPECT_EQ("a", Path("a/b").dirname());
EXPECT_EQ("a/b", Path("a/b/c/").dirname());
#endif // __WINDOWS__
// Check leading slashes get cleaned up properly.
#ifdef __WINDOWS__
EXPECT_EQ("\\", Path("\\a").dirname());
EXPECT_EQ("\\", Path("\\\\a").dirname());
EXPECT_EQ("\\", Path("\\a\\").dirname());
EXPECT_EQ("\\a", Path("\\a\\b").dirname());
EXPECT_EQ("\\\\a", Path("\\\\a\\\\b").dirname());
EXPECT_EQ("\\a\\b", Path("\\a\\b\\c").dirname());
#else
EXPECT_EQ("/", Path("/a").dirname());
EXPECT_EQ("/", Path("//a").dirname());
EXPECT_EQ("/", Path("/a/").dirname());
EXPECT_EQ("/a", Path("/a/b").dirname());
EXPECT_EQ("//a", Path("//a//b").dirname());
EXPECT_EQ("/a/b", Path("/a/b/c").dirname());
#endif // __WINDOWS__
// Check intermittent slashes get handled just like ::dirname does.
#ifdef __WINDOWS__
EXPECT_EQ("\\a\\\\b", Path("\\a\\\\b\\\\c\\\\").dirname());
EXPECT_EQ("\\\\a\\b", Path("\\\\a\\b\\\\c").dirname());
#else
EXPECT_EQ("/a//b", Path("/a//b//c//").dirname());
EXPECT_EQ("//a/b", Path("//a/b//c").dirname());
#endif // __WINDOWS__
// Check trailing slashes get cleaned up properly.
#ifdef __WINDOWS__
EXPECT_EQ(".", Path("a\\").dirname());
EXPECT_EQ("a\\b", Path("a\\b\\c").dirname());
EXPECT_EQ("\\a\\b", Path("\\a\\b\\c\\").dirname());
EXPECT_EQ("\\a\\b", Path("\\a\\b\\c\\\\").dirname());
EXPECT_EQ("\\a\\b", Path("\\a\\b\\c\\\\\\").dirname());
EXPECT_EQ("\\", Path("\\\\").dirname());
EXPECT_EQ("\\", Path("\\\\\\").dirname());
#else
EXPECT_EQ(".", Path("a/").dirname());
EXPECT_EQ("a/b", Path("a/b/c").dirname());
EXPECT_EQ("/a/b", Path("/a/b/c/").dirname());
EXPECT_EQ("/a/b", Path("/a/b/c//").dirname());
EXPECT_EQ("/a/b", Path("/a/b/c///").dirname());
EXPECT_EQ("/", Path("//").dirname());
EXPECT_EQ("/", Path("///").dirname());
#endif // __WINDOWS__
}
TEST(PathTest, Extension)
{
EXPECT_NONE(Path(".").extension());
EXPECT_NONE(Path("..").extension());
EXPECT_NONE(Path("a").extension());
#ifdef __WINDOWS__
EXPECT_NONE(Path("\\a").extension());
EXPECT_NONE(Path("\\").extension());
#else
EXPECT_NONE(Path("/a").extension());
EXPECT_NONE(Path("/").extension());
#endif // __WINDOWS__
#ifdef __WINDOWS__
EXPECT_NONE(Path("\\a.b\\c").extension());
#else
EXPECT_NONE(Path("/a.b/c").extension());
#endif // __WINDOWS__
EXPECT_SOME_EQ(".txt", Path("a.txt").extension());
#ifdef __WINDOWS__
EXPECT_SOME_EQ(".txt", Path("\\a\\b.txt").extension());
EXPECT_SOME_EQ(".txt", Path("\\a.b\\c.txt").extension());
#else
EXPECT_SOME_EQ(".txt", Path("/a/b.txt").extension());
EXPECT_SOME_EQ(".txt", Path("/a.b/c.txt").extension());
#endif // __WINDOWS__
EXPECT_SOME_EQ(".gz", Path("a.tar.gz").extension());
EXPECT_SOME_EQ(".bashrc", Path(".bashrc").extension());
#ifdef __WINDOWS__
EXPECT_SOME_EQ(".gz", Path("\\a.tar.gz").extension());
EXPECT_SOME_EQ(".bashrc", Path("\\.bashrc").extension());
#else
EXPECT_SOME_EQ(".gz", Path("/a.tar.gz").extension());
EXPECT_SOME_EQ(".bashrc", Path("/.bashrc").extension());
#endif // __WINDOWS__
}
TEST(PathTest, Join)
{
EXPECT_EQ("a%b", path::join("a", "b", '%'));
#ifndef __WINDOWS__
EXPECT_EQ("/", path::join("", ""));
EXPECT_EQ("/", path::join("", "", ""));
EXPECT_EQ("/a", path::join("", "a"));
EXPECT_EQ("a/", path::join("a", ""));
EXPECT_EQ("a/b", path::join("a", "b"));
#else
EXPECT_EQ("\\", path::join("", ""));
EXPECT_EQ("\\", path::join("", "", ""));
EXPECT_EQ("\\a", path::join("", "a"));
EXPECT_EQ("a\\", path::join("a", ""));
EXPECT_EQ("a\\b", path::join("a", "b"));
#endif // __WINDOWS__
#ifdef __WINDOWS__
EXPECT_EQ("a\\b\\c", path::join("a", "b", "c"));
EXPECT_EQ("\\a\\b\\c", path::join("\\a", "b", "c"));
#else
EXPECT_EQ("a/b/c", path::join("a", "b", "c"));
EXPECT_EQ("/a/b/c", path::join("/a", "b", "c"));
#endif // __WINDOWS__
EXPECT_EQ("", path::join(vector<string>()));
#ifdef __WINDOWS__
EXPECT_EQ("a\\b\\c", path::join(vector<string>({"a", "b", "c"})));
#else
EXPECT_EQ("a/b/c", path::join(vector<string>({"a", "b", "c"})));
#endif // __WINDOWS__
// TODO(cmaloney): This should join to ""
#ifdef __WINDOWS__
EXPECT_EQ("\\", path::join(vector<string>({"", "", ""})));
#else
EXPECT_EQ("/", path::join(vector<string>({"", "", ""})));
#endif // __WINDOWS__
// Interesting corner cases around being the first, middle, last.
#ifdef __WINDOWS__
EXPECT_EQ("\\asdf", path::join("\\", "asdf"));
EXPECT_EQ("\\", path::join("", "\\", ""));
EXPECT_EQ("ab\\", path::join("ab\\", "", "\\"));
EXPECT_EQ("\\ab", path::join("\\", "\\", "ab"));
EXPECT_EQ("ab\\", path::join("ab", "\\", "\\"));
EXPECT_EQ("\\ab", path::join("\\", "", "\\ab"));
#else
EXPECT_EQ("/asdf", path::join("/", "asdf"));
EXPECT_EQ("/", path::join("", "/", ""));
EXPECT_EQ("ab/", path::join("ab/", "", "/"));
EXPECT_EQ("/ab", path::join("/", "/", "ab"));
EXPECT_EQ("ab/", path::join("ab", "/", "/"));
EXPECT_EQ("/ab", path::join("/", "", "/ab"));
#endif // __WINDOWS__
// Check trailing and leading slashes get cleaned up.
#ifdef __WINDOWS__
EXPECT_EQ("a\\b\\c\\", path::join("a\\", "b\\", "c\\"));
EXPECT_EQ("\\a\\b\\c", path::join("\\a", "\\b", "\\c"));
EXPECT_EQ("\\a\\b\\c\\", path::join("\\a\\", "\\b\\", "\\c\\"));
EXPECT_EQ("a\\b\\c\\", path::join("a\\", "\\b\\", "\\c\\"));
#else
EXPECT_EQ("a/b/c/", path::join("a/", "b/", "c/"));
EXPECT_EQ("/a/b/c", path::join("/a", "/b", "/c"));
EXPECT_EQ("/a/b/c/", path::join("/a/", "/b/", "/c/"));
EXPECT_EQ("a/b/c/", path::join("a/", "/b/", "/c/"));
#endif // __WINDOWS__
}
TEST(PathTest, Absolute)
{
#ifdef __WINDOWS__
// Check absolute paths.
EXPECT_TRUE(path::absolute("C:\\foo\\bar\\baz"));
EXPECT_TRUE(path::absolute("c:\\"));
EXPECT_TRUE(path::absolute("C:/"));
EXPECT_TRUE(path::absolute("c:/"));
EXPECT_TRUE(path::absolute("X:\\foo"));
EXPECT_TRUE(path::absolute("X:\\foo"));
EXPECT_TRUE(path::absolute("y:\\bar"));
EXPECT_TRUE(path::absolute("y:/bar"));
EXPECT_TRUE(path::absolute("\\\\?\\"));
EXPECT_TRUE(path::absolute("\\\\?\\C:\\Program Files"));
EXPECT_TRUE(path::absolute("\\\\?\\C:/Program Files"));
EXPECT_TRUE(path::absolute("\\\\?\\C:\\Path"));
EXPECT_TRUE(path::absolute("\\\\server\\share"));
// Check invalid paths.
EXPECT_FALSE(path::absolute("abc:/"));
EXPECT_FALSE(path::absolute("1:/"));
EXPECT_TRUE(path::absolute("\\\\?\\relative"));
// Check relative paths.
EXPECT_FALSE(path::absolute("relative"));
EXPECT_FALSE(path::absolute("\\file-without-disk"));
EXPECT_FALSE(path::absolute("/file-without-disk"));
EXPECT_FALSE(path::absolute("N:file-without-dir"));
#else
// Check absolute paths.
EXPECT_TRUE(path::absolute("/"));
EXPECT_TRUE(path::absolute("/foo"));
EXPECT_TRUE(path::absolute("/foo/bar"));
EXPECT_TRUE(path::absolute("/foo/bar/../baz"));
// Check relative paths.
EXPECT_FALSE(path::absolute(""));
EXPECT_FALSE(path::absolute("."));
EXPECT_FALSE(path::absolute(".."));
EXPECT_FALSE(path::absolute("../"));
EXPECT_FALSE(path::absolute("./foo"));
EXPECT_FALSE(path::absolute("../foo"));
#endif // __WINDOWS__
}
TEST(PathTest, Comparison)
{
EXPECT_TRUE(Path("a") == Path("a"));
EXPECT_FALSE(Path("a") == Path("b"));
EXPECT_TRUE(Path("a") != Path("b"));
EXPECT_FALSE(Path("a") != Path("a"));
EXPECT_TRUE(Path("a") < Path("b"));
EXPECT_FALSE(Path("b") < Path("a"));
EXPECT_TRUE(Path("a") <= Path("b"));
EXPECT_TRUE(Path("a") <= Path("a"));
EXPECT_FALSE(Path("b") <= Path("a"));
EXPECT_TRUE(Path("b") > Path("a"));
EXPECT_FALSE(Path("a") > Path("a"));
EXPECT_TRUE(Path("b") >= Path("a"));
EXPECT_TRUE(Path("b") >= Path("b"));
EXPECT_FALSE(Path("a") >= Path("b"));
}
TEST(PathTest, FromURI)
{
#ifdef __WINDOWS__
const std::string absolute_path = "C:\\somedir\\somefile";
#else
const std::string absolute_path = "/somedir/somefile";
#endif // __WINDOWS__
EXPECT_EQ("", path::from_uri(""));
EXPECT_EQ(absolute_path, path::from_uri(absolute_path));
EXPECT_EQ(absolute_path, path::from_uri("file://" + absolute_path));
#ifdef __WINDOWS__
EXPECT_EQ(absolute_path, path::from_uri("file://C:/somedir/somefile"));
EXPECT_EQ(absolute_path, path::from_uri("C:/somedir/somefile"));
EXPECT_EQ(absolute_path, path::from_uri("C:\\somedir\\somefile"));
#endif // __WINDOWS__
}
class PathFileTest : public TemporaryDirectoryTest {};
TEST_F(PathFileTest, ImplicitConversion)
{
// Should be implicitly converted to string for the various os::_ calls.
const Path testfile(path::join(os::getcwd(), "file.txt"));
// Create the test file.
ASSERT_SOME(os::touch(testfile));
ASSERT_TRUE(os::exists(testfile));
// Open and close the file.
Try<int_fd> fd = os::open(
testfile,
O_RDONLY,
S_IRUSR | S_IRGRP | S_IROTH);
ASSERT_SOME(fd);
close(fd.get());
// Delete the file.
EXPECT_SOME(os::rm(testfile));
}