Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(stdlib): System path library #1452

Merged
merged 13 commits into from
Dec 3, 2022
Merged
295 changes: 295 additions & 0 deletions compiler/test/stdlib/path.test.gr
Original file line number Diff line number Diff line change
@@ -0,0 +1,295 @@
import Path from "path"
import Result from "result"
import Option from "option"
import List from "list"

let relFile = x => Option.unwrap(Path.relativeFile(x))
let relDir = x => Option.unwrap(Path.relativeDir(x))
let absFile = x => Option.unwrap(Path.absoluteFile(x))
let absDir = x => Option.unwrap(Path.absoluteDir(x))
alex-snezhko marked this conversation as resolved.
Show resolved Hide resolved

// test that a variety of properties hold for valid relative/absolute paths
record FileTestData {
pathStr: String,
expParent: String,
expStr: String,
expName: Option<String>,
expStem: Option<String>,
expExt: Option<String>,
}

let relFileTests = [
{
pathStr: "./dir/file.txt",
expParent: "./dir",
expStr: "./dir/file.txt",
expName: Some("file.txt"),
expStem: Some("file"),
expExt: Some(".txt"),
},
{
pathStr: "file",
expParent: ".",
expStr: "./file",
expName: Some("file"),
expStem: Some("file"),
expExt: None,
},
{
pathStr: "a.tar.gz",
expParent: ".",
expStr: "./a.tar.gz",
expName: Some("a.tar.gz"),
expStem: Some("a.tar"),
expExt: Some(".gz"),
},
{
pathStr: "../../file",
expParent: "../..",
expStr: "../../file",
expName: Some("file"),
expStem: Some("file"),
expExt: None,
},
{
pathStr: ".\\dir\\file.txt",
expParent: ".",
expStr: "./.\\dir\\file.txt",
alex-snezhko marked this conversation as resolved.
Show resolved Hide resolved
expName: Some(".\\dir\\file.txt"),
expStem: Some(".\\dir\\file"),
expExt: Some(".txt"),
},
]

List.forEach(({ pathStr, expParent, expStr, expName, expStem, expExt }) => {
let path = relFile(pathStr)
assert Path.toString(path, Path.Posix) == expStr
assert relDir(expParent) == Path.parent(path)
assert expName == Path.name(path)
assert expStem == Path.stem(path)
assert expExt == Path.extension(path)
}, relFileTests)

record RelDirTestData {
pathStr: String,
expParent: String,
expStr: String,
expName: Option<String>,
}

let relDirTests = [
{ pathStr: "dir/../../", expParent: "../..", expStr: "../", expName: None },
{ pathStr: ".git", expParent: ".", expStr: "./.git/", expName: Some(".git") },
{ pathStr: ".", expParent: "..", expStr: "./", expName: None },
{ pathStr: ".////", expParent: "..", expStr: "./", expName: None },
{ pathStr: "../", expParent: "../..", expStr: "../", expName: None },
]

List.forEach(({ pathStr, expParent, expStr, expName }: RelDirTestData) => {
let path = relDir(pathStr)
assert Path.toString(path, Path.Posix) == expStr
assert relDir(expParent) == Path.parent(path)
assert expName == Path.name(path)
}, relDirTests)

let absFileTests = [
{
pathStr: "/dir/file.txt",
expParent: "/dir",
expStr: "/dir/file.txt",
expName: Some("file.txt"),
expStem: Some("file"),
expExt: Some(".txt"),
},
{
pathStr: "/dir/../file",
expParent: "/",
expStr: "/file",
expName: Some("file"),
expStem: Some("file"),
expExt: None,
},
{
pathStr: "C:/Users/me.txt",
expParent: "C:/Users",
expStr: "C:/Users/me.txt",
expName: Some("me.txt"),
expStem: Some("me"),
expExt: Some(".txt"),
},
]

List.forEach(({ pathStr, expParent, expStr, expName, expStem, expExt }) => {
let path = absFile(pathStr)
assert Path.toString(path, Path.Posix) == expStr
assert absDir(expParent) == Path.parent(path)
assert expName == Path.name(path)
assert expStem == Path.stem(path)
assert expExt == Path.extension(path)
}, absFileTests)

record AbsDirTestData {
pathStr: String,
expParent: String,
expStr: String,
expRoot: Path.AbsoluteRoot,
expName: Option<String>,
}

let absDirTests = [
{
pathStr: "/../..",
expParent: "/",
expStr: "/",
expRoot: Path.Root,
expName: None,
},
{
pathStr: "/",
expParent: "/",
expStr: "/",
expRoot: Path.Root,
expName: None,
},
{
pathStr: "/bin/dir/..",
expParent: "/",
expStr: "/bin/",
expRoot: Path.Root,
expName: Some("bin"),
},
{
pathStr: "C:/",
expParent: "C:/",
expStr: "C:/",
expRoot: Path.Drive('C'),
expName: None,
},
{
pathStr: "c:/.././..",
expParent: "c:/",
expStr: "c:/",
expRoot: Path.Drive('c'),
expName: None,
},
]

List.forEach(({ pathStr, expParent, expStr, expRoot, expName }) => {
let path = absDir(pathStr)
assert Path.toString(path, Path.Posix) == expStr
assert absDir(expParent) == Path.parent(path)
assert expRoot == Path.root(path)
assert expName == Path.name(path)
}, absDirTests)

// test invalidly trying to construct paths
assert Path.relativeFile("./dir/") == None
assert Path.relativeDir("/usr/bin") == None
assert Path.relativeDir("C:/Users/me") == None
assert Path.absoluteDir("C:\\Users\\me") == None
assert Path.absoluteFile("/usr/file.txt/") == None
assert Path.absoluteFile("./file.txt") == None
assert Path.absoluteFile("file.txt") == None
assert Path.absoluteDir("../..") == None

record AppendTestData {
base: String,
toAppend: String,
final: String,
}

// test appending onto relative and absolute paths
let appendRelTests = [
alex-snezhko marked this conversation as resolved.
Show resolved Hide resolved
{ base: "dir", toAppend: "inner", final: "dir/inner" },
{ base: "./dir/", toAppend: "../../other", final: "../other" },
{ base: ".", toAppend: ".././../", final: "../.." },
]

List.forEach(({ base, toAppend, final }) => {
let path = relDir(base)
let expPath = relDir(final)
let append = Path.append(path, relDir(toAppend))
assert append == expPath
}, appendRelTests)

let appendAbsTests = [
alex-snezhko marked this conversation as resolved.
Show resolved Hide resolved
{ base: "/usr", toAppend: "./bin", final: "/usr/bin" },
{ base: "/usr", toAppend: "../bin", final: "/bin" },
{ base: "/", toAppend: "../..", final: "/" },
{ base: "C:/", toAppend: "../..", final: "C:/" },
]

List.forEach(({ base, toAppend, final }) => {
let path = absDir(base)
let expPath = absDir(final)
let append = Path.append(path, relDir(toAppend))
assert append == expPath
}, appendAbsTests)

record RelativeToTestData {
source: String,
dest: String,
result: Result<
Path.Path<Path.Relative, Path.Directory>,
Path.RelativizationError
>,
}
// test the relativeTo function
let valid = path => Ok(relDir(path))
let relativeToRelTests = [
alex-snezhko marked this conversation as resolved.
Show resolved Hide resolved
{ source: "./dir", dest: "./dir/inner", result: valid("./inner") },
{ source: "./dir", dest: ".", result: valid("..") },
{ source: ".", dest: ".", result: valid(".") },
{ source: "..", dest: "../../other", result: valid("../other") },
{ source: "..", dest: ".", result: Err(Path.ImpossibleRelativization) },
]

List.forEach(({ source, dest, result }) => {
let source = relDir(source)
let dest = relDir(dest)
assert Path.relativeTo(source, dest) == result
}, relativeToRelTests)

let relativeToAbsTests = [
alex-snezhko marked this conversation as resolved.
Show resolved Hide resolved
{ source: "/usr", dest: "/usr/bin", result: valid("./bin") },
{ source: "/", dest: "/", result: valid(".") },
{ source: "/usr/bin", dest: "/usr/bin", result: valid(".") },
{ source: "/usr/bin", dest: "/", result: valid("../..") },
{ source: "/usr/bin", dest: "/home/me", result: valid("../../home/me") },
{ source: "/bin", dest: "C:/Users", result: Err(Path.DifferentRoots) },
]

List.forEach(({ source, dest, result }) => {
let source = absDir(source)
let dest = absDir(dest)
assert Path.relativeTo(source, dest) == result
}, relativeToAbsTests)

// isDescendantOf tests
assert Path.isDescendantOf(absDir("/usr"), absDir("/usr/bin/../sbin"))
assert Path.isDescendantOf(relDir("dir"), relFile("dir/inner/file.txt"))
assert !Path.isDescendantOf(absDir("/usr"), absDir("/etc"))
assert !Path.isDescendantOf(absDir("/usr/bin"), absDir("/usr"))
assert !Path.isDescendantOf(relDir("../dir1"), relDir("./dir2"))
assert !Path.isDescendantOf(relDir("./dir1"), relDir("../../dir2"))

// wrapWithType tests
match (Path.wrapWithType(absFile("/file"))) {
Path.AbsoluteFile(_) => void,
_ => fail "",
alex-snezhko marked this conversation as resolved.
Show resolved Hide resolved
}
match (Path.wrapWithType(absDir("/dir"))) {
Path.AbsoluteDir(_) => void,
_ => fail "",
alex-snezhko marked this conversation as resolved.
Show resolved Hide resolved
}
match (Path.wrapWithType(relFile("file"))) {
Path.RelativeFile(_) => void,
_ => fail "",
alex-snezhko marked this conversation as resolved.
Show resolved Hide resolved
}
match (Path.wrapWithType(relDir("dir"))) {
Path.RelativeDir(_) => void,
_ => fail "",
alex-snezhko marked this conversation as resolved.
Show resolved Hide resolved
}

// miscellaneous tests
assert Path.toString(absDir("C:/Users/me"), Path.Windows) == "C:\\Users\\me\\"
1 change: 1 addition & 0 deletions compiler/test/suites/stdlib.re
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ describe("stdlib", ({test, testSkip}) => {
assertStdlib("marshal.test");
assertStdlib("number.test");
assertStdlib("option.test");
assertStdlib("path.test");
assertStdlib("pervasives.test");
assertStdlib("queue.test");
assertStdlib("range.test");
Expand Down
Loading