Resolve "Add path resolution tests"

Closes #108 (closed)

Edited by Ramon Nou

Merge request reports

Loading
+0 −2
Changes for test/CMakeLists.txt: 0 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -26,8 +26,6 @@ add_executable(gkfs_test_truncate truncate.cpp)
add_executable(gkfs_test_lseek lseek.cpp)
add_executable(gkfs_test_symlink symlink_test.cpp)

add_executable(gkfs_test_path_resolution path_resolution.cpp)

find_package(MPI)
if(${MPI_FOUND})
    set(SOURCE_FILES_MPI main_MPI.cpp)

test/path_resolution.cpp

deleted100644 → 0
+0 −161
Changes for test/path_resolution.cpp: 0 added lines, 161 removed lines.
Original line number Diff line number Diff line

#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <system_error>
#include <cassert>
#include <cstring>
#include <sys/stat.h>


static const std::string extdir = "/tmp/ext.tmp";
static const std::string ext_linkdir = "/tmp/link.tmp";
static const std::string nodir = "/tmp/notexistent";
static const std::string mountdir = "/tmp/mountdir";
static const std::string intdir = mountdir + "/int";


void setup() {
    int ret;

    // Clean external dir
    ret = rmdir(extdir.c_str());
    if (ret != 0) {
        if (errno != ENOENT) {
            std::cerr << "ERROR: cannot remove external dir: " <<
                strerror(errno) << std::endl;
            std::exit(EXIT_FAILURE);
        }
    }
    ret = mkdir(extdir.c_str(), 0770);
    if (ret != 0) {
        std::cerr << "ERROR: cannot create external dir: "
            << strerror(errno) << std::endl;
        std::exit(EXIT_FAILURE);
    }

    // Clean internal dir
    ret = rmdir(intdir.c_str());
    if (ret != 0) {
        if (errno != ENOENT) {
            std::cerr << "ERROR: cannot remove internal dir: " <<
                strerror(errno) << std::endl;
            std::exit(EXIT_FAILURE);
        }
    }
    ret = mkdir(intdir.c_str(), 0770);
    if (ret != 0) {
        std::cerr << "ERROR: cannot create internal dir: "
            << strerror(errno) << std::endl;
        std::exit(EXIT_FAILURE);
    }
}


void teardown() {
    // Clean external link
    if (unlink(ext_linkdir.c_str())) {
        if (errno != ENOENT) {
            std::cerr << "ERROR: cannot remove external dir: " <<
                strerror(errno) << std::endl;
        }
    }

    // Clean external dir
    if (rmdir(extdir.c_str())) {
        if (errno != ENOENT) {
            std::cerr << "ERROR: cannot remove external dir: " <<
                strerror(errno) << std::endl;
        }
    }

    // Clean internal dir
    if (rmdir(intdir.c_str())) {
        if (errno != ENOENT) {
            std::cerr << "ERROR: cannot remove internal dir: " <<
                strerror(errno) << std::endl;
        }
    }

}

void test_chdir(const std::string& dst, const std::string& expected) {
    char path[125];
    int ret = chdir(dst.c_str());
    if (ret != 0) {
        throw std::system_error(errno, std::system_category(),
                "ERROR: Failed to chdir into: " + dst);
    }

    char * cwd = getcwd(path, sizeof(path));
    if (cwd == NULL) {
        throw std::system_error(errno, std::system_category(),
                "ERROR: Failed to get current cwd");
    }

    if (std::string(path) != expected) {
        throw std::system_error(errno, std::system_category(),
                "ERROR: Expected path do not match");
    }
}


int main(int argc, char* argv[]) {

    if(std::atexit(teardown)) {
         std::cerr << "Teardown function registration failed" << std::endl;
         return EXIT_FAILURE;
    }

    setup();

    char buffIn[] = "oops.";
    char *buffOut = new char[strlen(buffIn) + 1 + 20 ];
    char path[125];

    struct stat st;
    int fd;
    int ret;

    // change to unexistent dir
    assert(stat(nodir.c_str(), &st) != 0);
    ret = chdir(nodir.c_str());
    if (ret == 0) {
        std::cerr << "ERROR: Succeeded on chdir to a non-existing dir" << std::endl;
        return EXIT_FAILURE;
    }
    if (errno != ENOENT) {
        std::cerr << "ERROR: wrong error number while opening non-existing file: " <<
            errno << std::endl;
        return EXIT_FAILURE;
    }

    // change to external dir
    ret = chdir(extdir.c_str());
    if (ret != 0) {
        std::cerr << "ERROR: Failed to chdir into external dir: " <<
            strerror(errno) << std::endl;
        return EXIT_FAILURE;
    }

    // test path resolution: from outside to inside
    test_chdir("../mountdir/int", intdir);

    // test path resolution: from inside to outside
    test_chdir("../../ext.tmp", extdir);

    // test complex path resolution
    test_chdir(mountdir + "/int/..//./int//../../../tmp/mountdir/../mountdir/./int/.//", intdir);

    // Create external link
    ret = symlink(extdir.c_str(), ext_linkdir.c_str());
    if (ret != 0) {
        std::cerr << "ERROR: Failed to make symbolic link: " <<
            strerror(errno) << std::endl;
        return EXIT_FAILURE;
    }

    test_chdir("../../link.tmp", extdir);

    test_chdir("../link.tmp/../link.tmp/../mountdir/int", intdir);
}
+97 −0
Changes for tests/integration/directories/test_pathresolution.py: 97 added lines, 0 removed lines.
Original line number Diff line number Diff line
################################################################################
#  Copyright 2018-2020, Barcelona Supercomputing Center (BSC), Spain           #
#  Copyright 2015-2020, Johannes Gutenberg Universitaet Mainz, Germany         #
#                                                                              #
#  This software was partially supported by the                                #
#  EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu).   #
#                                                                              #
#  This software was partially supported by the                                #
#  ADA-FS project under the SPPEXA project funded by the DFG.                  #
#                                                                              #
#  SPDX-License-Identifier: MIT                                                #
################################################################################

import harness
from pathlib import Path
import errno
import stat
import os
import ctypes
import sh
import sys
import pytest
from harness.logger import logger

nonexisting = "nonexisting"

#@pytest.mark.xfail(reason="invalid errno returned on success")
def test_pathresolution(gkfs_daemon, gkfs_client):
    """Testing different path resolution capabilities"""

    mountdir = gkfs_daemon.mountdir
    extdir = "/tmp/ext.tmp"
    ext_linkdir = "/tmp/link.tmp"
    nodir = "/tmp/notexistent"
    intdir = mountdir / "int"

    # Just clean if it exists, due to a failed test

    ret = gkfs_client.rmdir(extdir)
    try:
        os.unlink(ext_linkdir) # it is external
    except Exception as e:
        pass

    ret = gkfs_client.mkdir(
            extdir,
            stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)

    assert ret.retval == 0

    ret = gkfs_client.mkdir(
            intdir,
            stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)

    assert ret.retval == 0


    # test stat on existing dir
    ret = gkfs_client.stat(nodir)

    assert ret.retval == -1
    assert ret.errno == errno.ENOENT

    ret = gkfs_client.chdir(nodir)
    assert ret.retval == -1
    assert ret.errno == errno.ENOENT


    # Chdir to external dir

    ret = gkfs_client.chdir(extdir)
    assert ret.retval == 0

    ret = gkfs_client.getcwd_validate(str(intdir)+"../../../../../../../../../../../../../../../../../../.."+str(intdir))
    assert ret.path == str(intdir)
    assert ret.retval == 0

    # test path resolution: from inside to outside
    ret = gkfs_client.getcwd_validate("../../../../../../../../../../../.." + str(extdir))
    assert ret.path == str(extdir)
    assert ret.retval == 0

    # test complex path resolution
    ret = gkfs_client.getcwd_validate("../../../../../../../../../../../.." + str(extdir) + "/../../../../../../../../../../../.." + str(intdir))
    assert ret.path == str(intdir)
    assert ret.retval == 0

    # Teardown

    ret = gkfs_client.rmdir(extdir)
    assert ret.retval == 0

   #  Clean internal dir
    ret = gkfs_client.rmdir(intdir)
    assert ret.retval == 0

    return
+82 −0
Changes for tests/integration/directories/test_symlink.py: 82 added lines, 0 removed lines.
Original line number Diff line number Diff line
################################################################################
#  Copyright 2018-2020, Barcelona Supercomputing Center (BSC), Spain           #
#  Copyright 2015-2020, Johannes Gutenberg Universitaet Mainz, Germany         #
#                                                                              #
#  This software was partially supported by the                                #
#  EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu).   #
#                                                                              #
#  This software was partially supported by the                                #
#  ADA-FS project under the SPPEXA project funded by the DFG.                  #
#                                                                              #
#  SPDX-License-Identifier: MIT                                                #
################################################################################

import harness
from pathlib import Path
import errno
import stat
import os
import ctypes
import sh
import sys
import pytest
from harness.logger import logger

nonexisting = "nonexisting"

#@pytest.mark.xfail(reason="invalid errno returned on success")
def test_symlink(gkfs_daemon, gkfs_client):
    """Testing different path resolution capabilities: symlinks"""

    mountdir = gkfs_daemon.mountdir
    extdir = "/tmp/ext.tmp"
    ext_linkdir = "/tmp/link.tmp"
    nodir = "/tmp/notexistent"
    intdir = mountdir / "int"

    # Just clean if it exists, due to a failed test

    ret = gkfs_client.rmdir(extdir)
    try:
        os.unlink(ext_linkdir) # it is external
    except Exception as e:
        pass

    ret = gkfs_client.mkdir(
        extdir,
        stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)

    assert ret.retval == 0

    ret = gkfs_client.mkdir(
        intdir,
        stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)

    assert ret.retval == 0

    #Test external symlink

    ret = gkfs_client.symlink(extdir, ext_linkdir)
    assert ret.retval == 0

    ret = gkfs_client.getcwd_validate(str(extdir) + "/../link.tmp")
    assert ret.path == str(extdir)
    assert ret.retval == 0

    ret = gkfs_client.getcwd_validate(str(intdir) + "/../../../../../../../../../../../../../../../../../../../.."+str(extdir) + "/../link.tmp/../link.tmp/../../../../../../../../../../../../../../../../../../../../.."  + str(intdir))
    assert ret.path == str(intdir)
    assert ret.retval == 0

    # Teardown

    # Clean external link
    os.unlink(ext_linkdir)

    ret = gkfs_client.rmdir(extdir)
    assert ret.retval == 0

    #  Clean internal dir
    ret = gkfs_client.rmdir(intdir)
    assert ret.retval == 0

    return
+20 −40
Changes for tests/integration/harness/gkfs.io/util/file_compare.cpp: 20 added lines, 40 removed lines.
Original line number Diff line number Diff line
@@ -33,36 +33,32 @@ struct file_compare_options {
    std::string path_2{};
    size_t count{};

    REFL_DECL_STRUCT(file_compare_options,
                     REFL_DECL_MEMBER(bool, verbose),
    REFL_DECL_STRUCT(file_compare_options, REFL_DECL_MEMBER(bool, verbose),
                     REFL_DECL_MEMBER(std::string, path_1),
                     REFL_DECL_MEMBER(std::string, path_2),
                     REFL_DECL_MEMBER(size_t, count)
    );
                     REFL_DECL_MEMBER(size_t, count));
};

struct file_compare_output {
    int retval;
    int errnum;

    REFL_DECL_STRUCT(file_compare_output,
                     REFL_DECL_MEMBER(int, retval),
                     REFL_DECL_MEMBER(int, errnum)
    );
    REFL_DECL_STRUCT(file_compare_output, REFL_DECL_MEMBER(int, retval),
                     REFL_DECL_MEMBER(int, errnum));
};

void
to_json(json& record,
        const file_compare_output& out) {
to_json(json& record, const file_compare_output& out) {
    record = serialize(out);
}

int open_file(const std::string& path, bool verbose) {
int
open_file(const std::string& path, bool verbose) {
    auto fd = ::open(path.c_str(), O_RDONLY);
    if(fd == -1) {
        if(verbose) {
            fmt::print("open(pathname=\"{}\") = {}, errno: {} [{}]\n",
                       path, fd, errno, ::strerror(errno));
            fmt::print("open(pathname=\"{}\") = {}, errno: {} [{}]\n", path, fd,
                       errno, ::strerror(errno));
            return -1;
        }
        json out = file_compare_output{fd, errno};
@@ -72,7 +68,8 @@ int open_file(const std::string& path, bool verbose) {
    return fd;
}

size_t read_file(io::buffer& buf, int fd, size_t count) {
size_t
read_file(io::buffer& buf, int fd, size_t count) {
    ssize_t rv{};
    size_t total{};
    do {
@@ -131,42 +128,25 @@ file_compare_init(CLI::App& app) {

    // Create the option and subcommand objects
    auto opts = std::make_shared<file_compare_options>();
    auto* cmd = app.add_subcommand(
            "file_compare",
    auto* cmd = app.add_subcommand("file_compare",
                                   "Execute the truncate() system call");

    // Add options to cmd, binding them to opts
    cmd->add_flag(
            "-v,--verbose",
            opts->verbose,
            "Produce human writeable output"
    );

    cmd->add_option(
                    "path_1",
                    opts->path_1,
                    "Path to first file"
            )
    cmd->add_flag("-v,--verbose", opts->verbose,
                  "Produce human writeable output");

    cmd->add_option("path_1", opts->path_1, "Path to first file")
            ->required()
            ->type_name("");

    cmd->add_option(
                    "path_2",
                    opts->path_2,
                    "Path to second file"
            )
    cmd->add_option("path_2", opts->path_2, "Path to second file")
            ->required()
            ->type_name("");

    cmd->add_option(
                    "count",
                    opts->count,
                    "How many bytes to compare of each file"
            )
    cmd->add_option("count", opts->count,
                    "How many bytes to compare of each file")
            ->required()
            ->type_name("");

    cmd->callback([opts]() {
        file_compare_exec(*opts);
    });
    cmd->callback([opts]() { file_compare_exec(*opts); });
}
 No newline at end of file
Loading
Loading