describe("path", { it("returns paths UTF-8 encoded", { skip_on_os("solaris") expect_equal(Encoding(path("föö")), "UTF-8") }) it("returns paths UTF-8 encoded", { skip_on_os("solaris") expect_equal(Encoding(path("\U4F60\U597D.R")), "UTF-8") }) it("returns empty strings for empty inputs", { expect_equal(path(""), fs_path("")) expect_equal(path(character()), fs_path(character())) expect_equal(path("foo", character(), "bar"), fs_path(character())) }) it("propagates NA strings", { expect_equal(path(NA_character_), fs_path(NA_character_)) expect_equal(path("foo", NA_character_), fs_path(NA_character_)) expect_equal( path(c("foo", "bar"), c("baz", NA_character_)), fs_path(c("foo/baz", NA_character_)) ) }) it("appends a ext if provided", { expect_equal(path("foo", ext = "bar"), fs_path("foo.bar")) expect_equal( path(c("foo", "baz"), ext = "bar"), fs_path(c("foo.bar", "baz.bar")) ) expect_equal( path(c("foo", "baz", NA_character_), ext = "bar"), fs_path(c("foo.bar", "baz.bar", NA_character_)) ) }) it("does not double paths", { expect_equal(path("/", "foo"), fs_path("/foo")) expect_equal(path("\\", "foo"), fs_path("/foo")) expect_equal(path("", "foo"), fs_path("/foo")) expect_equal(path("foo/", "bar"), fs_path("foo/bar")) expect_equal(path("foo\\", "bar"), fs_path("foo/bar")) expect_equal(path("foo//", "bar"), fs_path("foo/bar")) # This could be a UNC path, so we keep the doubled path. expect_equal(path("//", "foo"), fs_path("//foo")) }) it("errors on paths which are too long", { expect_error(path(paste(rep("a", 100000), collapse = "")), "less than PATH_MAX") expect_error(do.call(path, as.list(rep("a", 100000))), "less than PATH_MAX") }) it("follows recycling rules", { expect_equal(path("foo", character()), fs_path(character())) expect_equal(path("foo", "bar"), fs_path("foo/bar")) expect_equal( path("foo", c("bar", "baz")), fs_path(c("foo/bar", "foo/baz")) ) expect_equal( path(c("foo", "qux"), c("bar", "baz")), fs_path(c("foo/bar", "qux/baz")) ) expect_error(path(c("foo", "qux", "foo2"), c("bar", "baz")), "Arguments must have consistent lengths", class = "invalid_argument") }) }) describe("path_wd", { it("returns an absolute path from the working directory", { x <- path_wd() expect_true(is_absolute_path(x)) expect_equal(x, path(getwd())) }) }) describe("path_real", { it("returns the real path for symbolic links", { with_dir_tree(list("foo/bar" = "test"), { link_create(path_real("foo"), "foo2") expect_equal(path_real("foo2"), path_real("foo")) }) }) it ("works with indirect symlinks", { skip_on_os("windows") with_dir_tree("foo", { wd <- path_wd() link_create(path("..", path_file(wd)), "self") link_create("self", "link") expect_equal(path_real("link"), wd) }) }) it ("works with parent symlinks", { skip_on_os("windows") # If there are symlinks in the parents of relative paths we need to resolve # them. # e.g. working directory is /usr/doc with 'doc' being a symlink to # /usr/share/doc. If we call `path_real("a")` we should return # /usr/share/doc/a. with_dir_tree("y", { wd <- path_wd() link_create("y", "k") withr::with_dir("k", { file_create("a") expect_equal(path_real("a"), path(wd, "/y/a")) unlink("a") }) }) }) it ("resolves paths before normalizing", { skip_on_os("windows") # if we have the following hierarchy: a/k/y # and a symbolic link 'link-y' pointing to 'y' in directory 'a', # then `path_real("link-y/..")` should return 'k', not 'a'. with_dir_tree("a/k/y", { link_create("a/k/y", "link-y") expect_equal(path_real("link-y/.."), path_real("a/k")) }) }) it ("resolves paths before normalizing", { skip_on_os("windows") # if we have the following hierarchy: a/k/y # and a symbolic link 'link-y' pointing to 'y' in directory 'a', # then `path_real("link-y/..")` should return 'k', not 'a'. with_dir_tree("k", { wd <- path_wd() link_create(wd, "link") withr::with_dir(path_dir(wd), { base <- path_file(wd) expect_equal(path_real(path(base, "link")), wd) expect_equal(path_real(path(base, "link/k")), path(wd, "k")) }) }) }) it("propagates NAs", { with_dir_tree(list("foo/bar" = "test"), { link_create(path_real("foo"), fs_path("foo2")) expect_equal(path_real(NA_character_), fs_path(NA_character_)) expect_equal( path_real(c("foo2", NA_character_)), fs_path(c(path_real("foo"), NA_character_)) ) }) }) it("converts inputs to character if required", { with_dir_tree(list("foo/bar" = "test"), { link_create(path_real("foo"), "2") expect_equal(path_real(NA), fs_path(NA_character_)) ## NA (logical) coerced to NA_character_ expect_equal(path_real(2), path_real("2")) }) }) }) describe("path_split", { it("returns the path split", { expect_equal(path_split("foo/bar")[[1]], c("foo", "bar")) expect_equal(path_split(c("foo/bar", "foo/baz")), list(c("foo", "bar"), c("foo", "baz"))) }) it("does not split the root path", { expect_equal(path_split("/usr/bin")[[1]], c("/", "usr", "bin")) expect_equal(path_split("c:/usr/bin")[[1]], c("C:", "usr", "bin")) expect_equal(path_split("X:/usr/bin")[[1]], c("X:", "usr", "bin")) expect_equal(path_split("//server/usr/bin")[[1]], c("//server", "usr", "bin")) expect_equal(path_split("\\\\server\\usr\\bin")[[1]], c("//server", "usr", "bin")) }) }) describe("path_tidy", { it("does not expand ~", { expect_equal(path_tidy("~/foo"), fs_path("~/foo")) expect_equal(path_tidy("~/foo/"), fs_path("~/foo")) expect_equal(path_tidy("~//foo"), fs_path("~/foo")) expect_equal(path_tidy("~//foo"), fs_path("~/foo")) expect_equal(path_tidy("~\\foo\\"), fs_path("~/foo")) }) it("always uses / for delimiting, never multiple / or trailing /", { expect_equal(path_tidy("foo/bar/baz"), fs_path("foo/bar/baz")) expect_equal(path_tidy("foo/bar/baz/"), fs_path("foo/bar/baz")) expect_equal(path_tidy("foo//bar//baz"), fs_path("foo/bar/baz")) expect_equal(path_tidy("foo//bar//baz//"), fs_path("foo/bar/baz")) expect_equal(path_tidy("foo\\bar\\baz"), fs_path("foo/bar/baz")) expect_equal(path_tidy("foo\\\\bar\\\\baz"), fs_path("foo/bar/baz")) expect_equal(path_tidy("//foo\\\\bar\\\\baz"), fs_path("//foo/bar/baz")) expect_equal(path_tidy("foo\\\\bar\\\\baz\\"), fs_path("foo/bar/baz")) expect_equal(path_tidy("foo\\\\bar\\\\baz\\\\"), fs_path("foo/bar/baz")) }) it("always capitalizes and appends windows root paths with /", { expect_equal(path_tidy("C:"), fs_path("C:/")) expect_equal(path_tidy("c:"), fs_path("C:/")) expect_equal(path_tidy("X:"), fs_path("X:/")) expect_equal(path_tidy("x:"), fs_path("X:/")) expect_equal(path_tidy("c:/"), fs_path("C:/")) expect_equal(path_tidy("c://"), fs_path("C:/")) expect_equal(path_tidy("c:\\"), fs_path("C:/")) expect_equal(path_tidy("c:\\\\"), fs_path("C:/")) }) it("passes NA along", { expect_equal(path_tidy(NA_character_), fs_path(NA_character_)) expect_equal( path_tidy(c("foo/bar", NA_character_)), fs_path(c("foo/bar", NA_character_)) ) }) it("works for non-UTF8 path", { x <- "folder//fa\xE7ile.txt/" Encoding(x) <- "latin1" out <- fs::path_tidy(x) expect_equal(Encoding(out), "UTF-8") expect_equal(out, fs_path("folder/façile.txt")) }) it("converts inputs to character if required", { expect_equal(path_tidy(c("foo/bar", NA)), fs_path(c("foo/bar", NA_character_))) expect_equal(path_tidy(1), fs_path("1")) }) }) describe("path_temp", { it("returned tidies tempdir()", { expect_equal(path_temp(), path_tidy(tempdir())) }) }) describe("path_ext", { it ("returns 0 length outputs for 0 length inputs", { expect_equal(path_ext(character()), character()) }) it ("returns the path extension, or \"\" if one does not exist", { expect_equal(path_ext("foo.bar"), "bar") expect_equal(path_ext("foo.boo.bar"), "bar") expect_equal(path_ext("foo.boo.biff.bar"), "bar") expect_equal(path_ext(".csh.rc"), "rc") expect_equal(path_ext("nodots"), "") expect_equal(path_ext(".cshrc"), "") expect_equal(path_ext("...manydots"), "") expect_equal(path_ext("...manydots.ext"), "ext") expect_equal(path_ext("manydots..."), "") expect_equal(path_ext("manydots...ext"), "ext") expect_equal(path_ext("."), "") expect_equal(path_ext(".."), "") expect_equal(path_ext("........"), "") expect_equal(path_ext(""), "") expect_equal(path_ext(".bar"), "") expect_equal(path_ext("foo/.bar"), "") expect_equal(path_ext(c("foo.bar", NA_character_)), c("bar", NA_character_)) expect_equal(path_ext("foo.bar/baz"), "") }) it ("works with non-ASCII inputs", { skip_if_not_utf8() expect_equal(path_ext("f\U00F6\U00F6.txt"), "txt") expect_equal(path_ext("f\U00F6\U00F6.t\U00E4r"), "t\U00E4r") }) it("returns a normal character vector", { expect_equal(class(path_dir("foo.sh")), "character") }) }) describe("path_ext_remove", { it ("removes the path extension", { expect_equal(path_ext_remove("foo.bar"), "foo") expect_equal(path_ext_remove("foo.boo.bar"), "foo.boo") expect_equal(path_ext_remove("foo.boo.biff.bar"), "foo.boo.biff") expect_equal(path_ext_remove(".csh.rc"), ".csh") expect_equal(path_ext_remove("nodots"), "nodots") expect_equal(path_ext_remove(".cshrc"), ".cshrc") expect_equal(path_ext_remove("...manydots"), "...manydots") expect_equal(path_ext_remove("...manydots.ext"), "...manydots") expect_equal(path_ext_remove("manydots..."), "manydots...") expect_equal(path_ext_remove("manydots...ext"), "manydots") expect_equal(path_ext_remove("."), ".") expect_equal(path_ext_remove(".."), "..") expect_equal(path_ext_remove("........"), "........") expect_equal(path_ext_remove(""), "") expect_equal(path_ext_remove(NA_character_), NA_character_) expect_equal(path_ext_remove(c("foo.bar", NA_character_)), c("foo", NA_character_)) expect_equal(path_ext_remove(".bar"), ".bar") expect_equal(path_ext_remove("foo/.bar"), "foo/.bar") expect_equal(path_ext_remove("foo.bar/abc.123"), "foo.bar/abc") expect_equal(path_ext_remove("foo.bar/abc"), "foo.bar/abc") }) it ("works with non-ASCII inputs", { skip_if_not_utf8() expect_equal(path_ext_remove("f\U00F6\U00F6.txt"), "f\U00F6\U00F6") expect_equal(path_ext_remove("f\U00F6\U00F6.t\U00E4r"), "f\U00F6\U00F6") }) }) describe("path_ext_set", { it ("replaces the path extension", { expect_equal(path_ext_set("foo.bar", "baz"), fs_path("foo.baz")) expect_equal(path_ext_set("foo.boo.bar", "baz"), fs_path("foo.boo.baz")) expect_equal( path_ext_set("foo.boo.biff.bar", "baz"), fs_path("foo.boo.biff.baz") ) expect_equal(path_ext_set(".csh.rc", "gz"), fs_path(".csh.gz")) expect_equal(path_ext_set("nodots", "bar"), fs_path("nodots.bar")) expect_equal(path_ext_set(".cshrc", "bar"), fs_path(".cshrc.bar")) expect_equal( path_ext_set("...manydots", "bar"), fs_path("...manydots.bar") ) expect_equal( path_ext_set("...manydots.ext", "bar"), fs_path("...manydots.bar") ) expect_equal(path_ext_set(".", "bar"), fs_path("..bar")) expect_equal(path_ext_set("..", "bar"), fs_path("...bar")) expect_equal(path_ext_set("........", "bar"), fs_path(".........bar")) expect_equal(path_ext_set("", "bar"), fs_path(".bar")) expect_equal(path_ext_set(NA_character_, "bar"), fs_path(NA_character_)) expect_equal( path_ext_set(c("foo", NA_character_), "bar"), fs_path(c("foo.bar", NA_character_)) ) expect_equal(path_ext_set(".bar", "baz"), fs_path(".bar.baz")) expect_equal(path_ext_set("foo/.bar", "baz"), fs_path("foo/.bar.baz")) expect_equal(path_ext_set("foo", ""), fs_path("foo")) }) it ("works the same with and without a leading . for ext", { expect_equal(path_ext_set("foo", "bar"), fs_path("foo.bar")) expect_equal(path_ext_set("foo", ".bar"), fs_path("foo.bar")) }) it ("only removes a leading . from the extension", { expect_equal(path_ext_set("foo", "b.ar"), fs_path("foo.b.ar")) expect_equal(path_ext_set("foo", ".b.ar"), fs_path("foo.b.ar")) }) it ("works with multiple paths (#205)", { multiple_paths <- c("a", "b") expect_equal( path_ext_set(multiple_paths, "csv"), fs_path(c("a.csv", "b.csv")) ) }) it ("works with multiple extensions (#250)", { multiple_paths <- c("a", "b") multiple_exts <- c("csv", "tsv") expect_equal( path_ext_set(multiple_paths, multiple_exts), fs_path(c("a.csv", "b.tsv")) ) expect_error(path_ext_set(multiple_paths, c(multiple_exts, "xls")), class = "fs_error", "consistent lengths") }) it ("works with non-ASCII inputs", { skip_if_not_utf8() expect_equal( path_ext_set("f\U00F6\U00F6.txt", "bar"), fs_path("f\U00F6\U00F6.bar") ) expect_equal( path_ext_set("f\U00F6\U00F6.t\U00E4r", "bar"), fs_path("f\U00F6\U00F6.bar") ) }) }) describe("path_ext<-", { it ("replaces the path extension", { x <- "...manydots" path_ext(x) <- "bar" expect_equal(x, fs_path("...manydots.bar")) }) }) # test cases derived from https://github.com/python/cpython/blob/6f0eb93183519024cb360162bdd81b9faec97ba6/Lib/test/test_posixpath.py#L276 describe("path_norm", { it ("works with POSIX paths", { expect_equal(path_norm(""), fs_path(".")) expect_equal(path_norm(""), fs_path(".")) expect_equal(path_norm(".."), fs_path("..")) expect_equal(path_norm("/../../.."), fs_path("/")) expect_equal(path_norm("/../.././.."), fs_path("/")) expect_equal(path_norm("../.././.."), fs_path("../../..")) expect_equal(path_norm("/"), fs_path("/")) expect_equal(path_norm("//"), fs_path("/")) expect_equal(path_norm("///"), fs_path("/")) expect_equal(path_norm("//foo"), fs_path("//foo")) expect_equal(path_norm("//foo/.//bar//"), fs_path("//foo/bar")) expect_equal(path_norm("/foo/.//bar//.//..//.//baz"), fs_path("/foo/baz")) expect_equal(path_norm("/..//./foo/.//bar"), fs_path("/foo/bar")) }) it ("works with POSIX paths", { expect_equal(path_norm("A//////././//.//B"), fs_path("A/B")) expect_equal(path_norm("A/./B"), fs_path("A/B")) expect_equal(path_norm("A/foo/../B"), fs_path("A/B")) expect_equal(path_norm("C:A//B"), fs_path("C:A/B")) expect_equal(path_norm("D:A/./B"), fs_path("D:A/B")) expect_equal(path_norm("e:A/foo/../B"), fs_path("E:A/B")) expect_equal(path_norm("C:///A//B"), fs_path("C:/A/B")) expect_equal(path_norm("D:///A/./B"), fs_path("D:/A/B")) expect_equal(path_norm("e:///A/foo/../B"), fs_path("E:/A/B")) expect_equal(path_norm(".."), fs_path("..")) expect_equal(path_norm("."), fs_path(".")) expect_equal(path_norm(""), fs_path(".")) expect_equal(path_norm("/"), fs_path("/")) expect_equal(path_norm("c:/"), fs_path("C:/")) expect_equal(path_norm("/../.././.."), fs_path("/")) expect_equal(path_norm("c:/../../.."), fs_path("C:/")) expect_equal(path_norm("../.././.."), fs_path("../../..")) expect_equal(path_norm("C:////a/b"), fs_path("C:/a/b")) expect_equal( path_norm("//machine/share//a/b"), fs_path("//machine/share/a/b") ) expect_equal(path_norm("\\\\?\\D:/XY\\Z"), fs_path("//?/D:/XY/Z")) }) it ("works with missing values", { expect_equal(path_norm(NA), fs_path(NA_character_)) expect_equal(path_norm(c("foo", NA)), fs_path(c("foo", NA))) expect_equal( path_norm(c(NA, NA)), fs_path(c(NA_character_, NA_character_)) ) }) }) # Test cases derived from https://github.com/python/cpython/blob/6f0eb93183519024cb360162bdd81b9faec97ba6/Lib/test/test_posixpath.py describe("path_common", { it ("finds the common path", { expect_error(path_common(c("/usr", "usr")), "Can't mix", class = "fs_error") expect_error(path_common(c("usr", "/usr")), "Can't mix", class = "fs_error") expect_equal(path_common(c("/usr/local")), fs_path("/usr/local")) expect_equal( path_common(c("/usr/local", "/usr/local")), fs_path("/usr/local") ) expect_equal( path_common(c("/usr/local/", "/usr/local")), fs_path("/usr/local") ) expect_equal( path_common(c("/usr/local/", "/usr/local/")), fs_path("/usr/local") ) expect_equal( path_common(c("/usr//local/bin", "/usr/local//bin")), fs_path("/usr/local/bin") ) expect_equal( path_common(c("/usr/./local", "/./usr/local")), fs_path("/usr/local") ) expect_equal( path_common(c("/", "/dev")), fs_path("/") ) expect_equal( path_common(c("/usr", "/dev")), fs_path("/") ) expect_equal( path_common(c("/usr/lib/", "/usr/lib/python3")), fs_path("/usr/lib") ) expect_equal( path_common(c("/usr/lib/", "/usr/lib64/")), fs_path("/usr") ) expect_equal( path_common(c("/usr/lib", "/usr/lib64")), fs_path("/usr") ) expect_equal( path_common(c("/usr/lib/", "/usr/lib64")), fs_path("/usr") ) expect_equal( path_common(c("spam")), fs_path("spam") ) expect_equal( path_common(c("spam", "spam")), fs_path("spam") ) expect_equal( path_common(c("spam", "alot")), fs_path("") ) expect_equal( path_common(c("and/jam", "and/spam")), fs_path("and") ) expect_equal( path_common(c("and//jam", "and/spam//")), fs_path("and") ) expect_equal( path_common(c("and/./jam", "./and/spam")), fs_path("and") ) expect_equal(path_common(c("and/jam", "and/spam", "alot")), fs_path("")) expect_equal(path_common(c("and/jam", "and/spam", "and")), fs_path("and")) expect_equal(path_common(c("")), fs_path("")) expect_equal(path_common(c("", "spam/alot")), fs_path("")) expect_error(path_common(c("", "/spam/alot")), "Can't mix", class = "fs_error") }) it("returns NA if any input is NA", { expect_equal(path_common(NA), fs_path(NA_character_)) expect_equal(path_common(c("and/jam", NA)), fs_path(NA_character_)) expect_equal(path_common(c("and/jam", NA, "and")), fs_path(NA_character_)) }) }) describe("path_has_parent", { it("works on single paths", { expect_false(path_has_parent("foo", "bar")) expect_false(path_has_parent("foo", "foo/bar")) expect_false(path_has_parent("/usr/var2/log", "/usr/var")) expect_true(path_has_parent("foo/bar", "foo")) expect_true(path_has_parent("path/myfiles/myfile", "path/to/files/../../myfiles")) }) it("works with multiple paths", { expect_equal(path_has_parent(c("/a/b/c", "x/y"), "/a/b"), c(TRUE, FALSE)) expect_equal(path_has_parent("/a/b/c", c("/a/b", "/x/y")), c(TRUE, FALSE)) expect_error(path_has_parent(c("/a/b/c", "x/y"), c("/a/b", "x/y", "foo/bar")), "consistent lengths", class = "invalid_argument") }) }) describe("path_join", { it("converts inputs to character if required", { expect_equal(path_join(c("a", NA)), path_join(c("a", NA_character_))) expect_equal(path_join(c("a", 1)), path_join(c("a", "1"))) expect_equal(path_join(list(c("a", 1), c("a/b", 2))), fs_path(c(path_join(c("a", "1")), path_join(c("a/b", "2"))))) }) it("works with list inputs", { expect_equal(path_join(list(c("foo", "bar"), c("a/b", "c"))), fs_path(c(path_join(c("foo", "bar")), path_join(c("a/b", "c"))))) expect_equal(path_join(list(NA, c("a", 1), c("a/b", 2))), fs_path(c(path_join(NA_character_), path_join(c("a", "1")), path_join(c("a/b", "2"))))) }) }) # derived from https://github.com/python/cpython/blob/6f0eb93183519024cb360162bdd81b9faec97ba6/Lib/test/test_posixpath.py#L483 describe("path_rel", { it("works for POSIX paths", { cur_dir <- path_file(getwd()) expect_equal(path_rel("a"), fs_path("a")) expect_equal(path_rel(path_abs("a")), fs_path("a")) expect_equal(path_rel("a/b"), fs_path("a/b")) expect_equal(path_rel("../a/b"), fs_path("../a/b")) expect_equal(path_rel("a", "../b"), path_join(c("..", cur_dir, "a"))) expect_equal(path_rel("a/b", "../c"), path_join(c("..", cur_dir, "a", "b"))) expect_equal(path_rel("a", "b/c"), fs_path("../../a")) expect_equal(path_rel("a", "a"), fs_path(".")) expect_equal( path_rel("/foo/bar/bat", "/x/y/z"), fs_path("../../../foo/bar/bat") ) expect_equal(path_rel("/foo/bar/bat", "/foo/bar"), fs_path("bat")) expect_equal(path_rel("/foo/bar/bat", "/"), fs_path("foo/bar/bat")) expect_equal(path_rel("/", "/foo/bar/bat"), fs_path("../../..")) expect_equal(path_rel("/foo/bar/bat", "/x"), fs_path("../foo/bar/bat")) expect_equal(path_rel("/x", "/foo/bar/bat"), fs_path("../../../x")) expect_equal(path_rel("/", "/"), fs_path(".")) expect_equal(path_rel("/a", "/a"), fs_path(".")) expect_equal(path_rel("/a/b", "/a/b"), fs_path(".")) expect_equal( path_rel(c("a", "a/b", "a/b/c"), "a/b"), fs_path(c("..", ".", "c")) ) expect_error( path_rel(c("a", "a/b", "a/b/c"), c("a/b", "a")), "`start` must be a single path to a starting directory", fixed = TRUE ) }) it("works for windows paths", { expect_equal( path_rel("c:/foo/bar/bat", "c:/x/y"), fs_path("../../foo/bar/bat") ) expect_equal( path_rel("//conky/mountpoint/a", "//conky/mountpoint/b/c"), fs_path("../../a") ) expect_equal( path_rel("d:/Users/a", "D:/Users/b"), fs_path("../a") ) }) it("expands path before computing relativity", { expect_equal(path_rel("/foo/bar/baz", "~"), path_rel("/foo/bar/baz", path_expand("~"))) expect_equal(path_rel("~/foo/bar/baz", "~"), fs_path("foo/bar/baz")) }) it("propagates NAs", { expect_equal(path_rel(NA_character_), fs_path(NA_character_)) expect_equal(path_rel("/foo/bar/baz", NA_character_), fs_path(NA_character_)) }) it("can be reversed by path_abs", { skip_on_os("windows") f <- file_temp() expect_equal(path_abs(path_rel(f)), f) home <- path_home() home_f <- path_abs(path_home("../../foo/bar/baz")) expect_equal(path_abs(path_rel(home_f, start = home), start = home), home_f) }) }) describe("path_abs", { it("uses the start parameter", { expect_equal(path_abs("b", "a"), path_abs("a/b")) }) }) describe("path_home", { # The trailing slash is needed to ensure we get path expansion # on POSIX systems when readline support is not built in. (#60) it("is equivalent to path_expand(\"~/\")", { expect_equal(path_home(), path_tidy(path_expand("~/"))) }) }) describe("path_dir", { it("works like dirname for normal paths", { expect_equal(path_dir("foo/bar"), "foo") expect_equal(path_dir("bar"), ".") expect_equal(path_dir(c("foo/bar", "baz")), c("foo", ".")) }) it("propagates NAs", { expect_equal(path_dir(NA_character_), NA_character_) expect_equal(path_dir(c("foo/bar", NA)), c("foo", NA_character_)) }) it("returns a normal character vector", { expect_equal(class(path_dir("foo/bar")), "character") }) }) describe("path_file", { it("works like dirname for normal paths", { expect_equal(path_file("foo/bar"), "bar") expect_equal(path_file("bar"), "bar") expect_equal(path_file(c("foo/bar", "baz")), c("bar", "baz")) }) it("propagates NAs", { expect_equal(path_file(NA_character_), NA_character_) expect_equal(path_file(c("foo/bar", NA)), c("bar", NA_character_)) }) it("returns a normal character vector", { expect_equal(class(path_dir("foo/bar")), "character") }) }) # These tests were adapted from # https://github.com/python/cpython/blob/48e8c82fc63d2ddcddce8aa637a892839b551619/Lib/test/test_ntpath.py, # hence the flying circus names, but I like dead parrots too, so keeping them. describe("path_expand", { it("works on windows", { withr::local_envvar(c(FS_IS_WINDOWS = "TRUE")) withr::with_envvar(c("USERPROFILE" = NA, "HOMEDRIVE" = NA, "HOMEPATH" = NA), { expect_equal(path_expand("~test"), fs_path("~test")) }) withr::with_envvar(c("USERPROFILE" = NA, "HOMEDRIVE" = "C:\\", "HOMEPATH" = "eric\\idle"), { expect_equal(path_expand("~"), fs_path("C:/eric/idle")) expect_equal(path_expand("~test"), fs_path("C:/eric/test")) }) withr::with_envvar(c("USERPROFILE" = NA, "HOMEDRIVE" = NA, "HOMEPATH" = "eric/idle"), { expect_equal(path_expand("~"), fs_path("eric/idle")) expect_equal(path_expand("~test"), fs_path("eric/test")) }) withr::with_envvar(c("USERPROFILE" = "C:\\idle\\eric"), { expect_equal(path_expand("~"), fs_path("C:/idle/eric")) expect_equal(path_expand("~test"), fs_path("C:/idle/test")) expect_equal( path_expand("~test/foo/bar"), fs_path("C:/idle/test/foo/bar") ) expect_equal( path_expand("~test/foo/bar/"), fs_path("C:/idle/test/foo/bar") ) expect_equal( path_expand("~test\\foo\\bar"), fs_path("C:/idle/test/foo/bar") ) expect_equal( path_expand("~test\\foo\\bar\\"), fs_path("C:/idle/test/foo/bar") ) expect_equal( path_expand("~/foo/bar"), fs_path("C:/idle/eric/foo/bar") ) expect_equal( path_expand("~\\foo\\bar"), fs_path("C:/idle/eric/foo/bar") ) }) withr::with_envvar(c("USERPROFILE" = "C:\\idle\\eric", "R_FS_HOME" = "C:\\john\\cleese"), { # R_FS_HOME overrides userprofile expect_equal(path_expand("~"), fs_path("C:/john/cleese")) expect_equal(path_expand("~test"), fs_path("C:/john/test")) }) }) it("repects R_FS_HOME", { withr::with_envvar(c("R_FS_HOME" = "/foo/bar"), { expect_equal(path_expand("~"), fs_path("/foo/bar")) expect_equal(path_expand("~test"), fs_path("/foo/test")) }) }) })