Commit 8113718a authored by Julius Athenstaedt's avatar Julius Athenstaedt Committed by Marc Vef
Browse files

path unit test

parent 6a960853
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ std::pair<bool, std::string>
resolve(const std::string& path, bool resolve_last_link = true);

std::pair<bool, std::string>
resolve_new(const std::string& path, const std::string& mountdir);
resolve_new(const std::string& path);

[[deprecated(
        "Use GKFS_USE_LEGACY_PATH_RESOLVE to use old implementation")]] bool
+32 −15
Original line number Diff line number Diff line
@@ -131,46 +131,63 @@ resolve(const string& path, bool resolve_last_link) {
    bool is_in_path = resolve(path, resolved, resolve_last_link);
    return make_pair(is_in_path, resolved);
#else
    return resolve_new(path, CTX->mountdir());
    return resolve_new(path);
#endif
}

pair<bool, string>
resolve_new(const string& path, const string& mountdir) {
    LOG(DEBUG, "path: \"{}\", mountdir: \"{}\"", path, mountdir);
resolve_new(const string& path) {
    LOG(DEBUG, "path: \"{}\", mountdir: \"{}\"", path, CTX->mountdir());

    if(path.empty()) {
        return make_pair(false, "/");
    }

    string resolved = "";
    stack<size_t> last_component_pos;
    const string absolute_path = (path.at(0) == path::separator)
                                         ? path
                                         : CTX->cwd() + path::separator + path;

    for(size_t start = 0; start < path.size(); start++) {
        size_t end = path.find(path::separator, start);
    for(size_t start = 0; start < absolute_path.size(); start++) {
        size_t end = absolute_path.find(path::separator, start);
        // catches the case without separator at the end
        if(end == string::npos) {
            end = absolute_path.size();
        }
        size_t comp_size = end - start;
        if(comp_size == 1 && path.at(start) == path::separator) {
            // should I use same while loop as in the original here?
        if(comp_size == 0 && absolute_path.at(start) == path::separator) {
            continue;
        }
        if(comp_size == 1 && path.at(start) == '.') {
        if(comp_size == 1 && absolute_path.at(start) == '.') {
            // component is '.', we skip it
            continue;
        }
        if(comp_size == 2 && path.at(start) == '.' &&
           path.at(start + 1) == '.') {
        if(comp_size == 2 && absolute_path.at(start) == '.' &&
           absolute_path.at(start + 1) == '.') {
            // component is '..', we skip it
            LOG(DEBUG, "path: \"{}\", mountdir: \"{}\"", path, mountdir);
            LOG(DEBUG, "path: \"{}\", mountdir: \"{}\"", absolute_path,
                CTX->mountdir());
            if(last_component_pos.empty()) {
                resolved = "/";
            } else {
                resolved.erase(last_component_pos.top());
                last_component_pos.pop();
            }
            continue;
        }
        // add `/<component>` to the reresolved path
        resolved.push_back(path::separator);
        last_component_pos.push(resolved.size() - 1);
        resolved.append(path, start, comp_size);
        resolved.append(absolute_path, start, comp_size);
        start = end;

#ifdef GKFS_FOLLOW_EXTERNAL_SYMLINKS
        resolved = follow_symlinks(resolved);
#endif
    }

    if(resolved.substr(0, mountdir.size()) == mountdir) {
    if(resolved.substr(0, CTX->mountdir().size()) == CTX->mountdir()) {
        resolved.erase(1, CTX->mountdir().size());
        LOG(DEBUG, "internal: \"{}\"", resolved);
        return make_pair(true, resolved);
+74 −49
Original line number Diff line number Diff line
@@ -28,86 +28,111 @@

#include <catch2/catch.hpp>
#include <client/path.hpp>
#include <client/preload_context.hpp>
#include <client/preload.hpp>

// mock CTX
class text_context {
	std::string mntdir = "/tmp/gkfs_mount";
	const std::string& mountdir(){
		return mntdir;
	}
};
#define CTX text_context
#define TEST_PAIR(p, s, s2)                                                    \
    REQUIRE(p.first == s);                                                     \
    REQUIRE(p.second == s2);

SCENARIO(" resolve fn should handle empty path ",
         "[test_path][empty]") {
SCENARIO(" resolve fn should handle empty path ", "[test_path][empty]") {

    GIVEN(" a mount path ") {

		    std::string mntpath = "/tmp/gkfs_mount";
        CTX->mountdir("/home/foo/tmp/gkfs_mount");
        CTX->cwd("/home/foo");

        WHEN(" resolve with empty path ") {
            THEN(" / should be returned ") {
                REQUIRE(gkfs::path::resolve_new("").second ==  "/");
            THEN("") {
                TEST_PAIR(gkfs::path::resolve_new("./tmp/gkfs_mount"), true,
                          "/");
                TEST_PAIR(gkfs::path::resolve_new(""), false, "/");
                TEST_PAIR(gkfs::path::resolve_new("///"), false, "/");
                TEST_PAIR(gkfs::path::resolve_new("tmp/../gkfs_mount"), false,
                          "/home/foo/gkfs_mount");
            }
        }
    }
}

// TODO check pair.first is true
SCENARIO(" resolve fn should handle internal paths ",
         "[test_path][external paths]") {

    GIVEN(" a mount path ") {

		    std::string mntpath = "/tmp/gkfs_mount";

        WHEN(" resolve with relative path ") {
            THEN(" iwas ") {
                REQUIRE(gkfs::path::resolve_new("/home/foo/../../tmp/./gkfs_mount/bar/./").second ==  "/bar/");
            }
            THEN(" iwas ") {
                REQUIRE(gkfs::path::resolve_new("/tmp/../tmp/gkfs_mount/bar/./").second ==  "/bar/");
        CTX->mountdir("/home/foo/tmp/gkfs_mount");
        CTX->cwd("/home/foo");

        WHEN(" resolve with absolute path ") {
            THEN(" ") {
                TEST_PAIR(gkfs::path::resolve_new(
                                  "/home/foo/../foo//tmp/./gkfs_mount/bar/./"),
                          true, "/bar");
                TEST_PAIR(gkfs::path::resolve_new(
                                  "/home/foo/tmp/../tmp/gkfs_mount/bar/./"),
                          true, "/bar");
                TEST_PAIR(gkfs::path::resolve_new(
                                  "/home/foo/tmp/./gkfs_mount/bar/./"),
                          true, "/bar");
                TEST_PAIR(gkfs::path::resolve_new(
                                  "/home/foo/tmp/gkfs_mount/bar/./"),
                          true, "/bar");
                TEST_PAIR(gkfs::path::resolve_new(
                                  "/home/foo/../../home/foo/./tmp/gkfs_mount/"),
                          true, "/");
            }
            THEN(" iwas ") {
                REQUIRE(gkfs::path::resolve_new("/tmp/./gkfs_mount/bar/./").second ==  "/bar/");
        }
            THEN(" iwas ") {
                REQUIRE(gkfs::path::resolve_new("/tmp/gkfs_mount/bar/./").second ==  "/bar/");
            }
            THEN(" iwas ") {
                REQUIRE(gkfs::path::resolve_new("/home/foo/../.././tmp/gkfs_mount/").second ==  "/");

        WHEN(" resolve with relative path ") {
            THEN(" ") {
                TEST_PAIR(gkfs::path::resolve_new(
                                  "./sme/blub/../../tmp/./gkfs_mount/bar/./"),
                          true, "/bar");
                TEST_PAIR(gkfs::path::resolve_new(
                                  "./tmp/../tmp/gkfs_mount/bar/./"),
                          true, "/bar");
            }
        }
    }
}

// TODO check pair.first is false
SCENARIO(" resolve fn should handle external paths ",
         "[test_path][external paths]") {

    GIVEN(" a mount path ") {

		    std::string mntpath = "/tmp/gkfs_mount";

        WHEN(" resolve with relative path ") {
            THEN(" iwas ") {
                REQUIRE(gkfs::path::resolve_new("/home/foo/../ar/.").second ==  "/home/bar");
            }
            THEN(" iwas ") {
                REQUIRE(gkfs::path::resolve_new("/home/foo/../bar/./").second ==  "/home/bar/");
            }
            THEN(" iwas ") {
                REQUIRE(gkfs::path::resolve_new("/home/foo/../bar/../").second ==  "/home/");
        CTX->mountdir("/home/foo/tmp/gkfs_mount");
        CTX->cwd("/home/foo");

        WHEN(" resolve with absolute path ") {
            THEN(" ") {
                TEST_PAIR(gkfs::path::resolve_new("/home/foo/../bar/."), false,
                          "/home/bar");
                TEST_PAIR(gkfs::path::resolve_new("/home/foo/../bar/./"), false,
                          "/home/bar");
                TEST_PAIR(gkfs::path::resolve_new("/home/foo/../bar/../"),
                          false, "/home");
                TEST_PAIR(gkfs::path::resolve_new("/home/foo/../../"), false,
                          "/");
                TEST_PAIR(gkfs::path::resolve_new("/home/foo/./bar/../"), false,
                          "/home/foo");
                TEST_PAIR(gkfs::path::resolve_new("/home/./../tmp/"), false,
                          "/tmp");
                TEST_PAIR(gkfs::path::resolve_new(
                                  "/home/./../tmp/gkfs_mount/../"),
                          false, "/tmp");
                TEST_PAIR(gkfs::path::resolve_new("/home/random/device"), false,
                          "/home/random/device");
            }
            THEN(" iwas ") {
                REQUIRE(gkfs::path::resolve_new("/home/foo/../../").second ==  "/");
        }
            THEN(" iwas ") {
                REQUIRE(gkfs::path::resolve_new("/home/foo/./bar/../").second ==  "/home/foo/");
            }
            THEN(" iwas ") {
                REQUIRE(gkfs::path::resolve_new("/home/./../tmp/").second ==  "/tmp/");

        WHEN(" resolve with relative path ") {
            THEN(" ") {
                TEST_PAIR(gkfs::path::resolve_new(
                                  "./sme/blub/../tmp/./gkfs_mount/bar/./"),
                          false, "/home/foo/sme/tmp/gkfs_mount/bar");
                TEST_PAIR(gkfs::path::resolve_new("./tmp//bar/./"), false,
                          "/home/foo/tmp/bar");
                TEST_PAIR(gkfs::path::resolve_new("../../../.."), false, "/");
            }
        }
    }