Commit 6d5e9b09 authored by Alberto Miranda's avatar Alberto Miranda ♨️
Browse files

Add API tests

parent 0fee202a
Loading
Loading
Loading
Loading

tests/Makefile.am

0 → 100644
+80 −0
Original line number Diff line number Diff line
# Copyright (C) 2017 Barcelona Supercomputing Center
#                    Centro Nacional de Supercomputacion
#
# This file is part of the Data Scheduler, a daemon for tracking and managing
# requests for asynchronous data transfer in a hierarchical storage environment.
#
# See AUTHORS file in the top level directory for information
# regarding developers and contributors.
#
# The Data Scheduler is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Data Scheduler is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Data Scheduler.  If not, see <http://www.gnu.org/licenses/>.
#

AM_CPPFLAGS = -I m4

TESTS = api

check_PROGRAMS = $(TESTS)

END = 

api_CXXFLAGS = \
	-Wall -Wextra \
	$(END)

api_CPPFLAGS = \
	-I$(top_srcdir)/include \
	-I$(top_srcdir)/rpc \
	-I$(top_srcdir)/src \
	$(END)

api_SOURCES = \
	catch.hpp \
	api-main.cpp \
	api-job-register.cpp \
	api-job-update.cpp \
	api-job-unregister.cpp \
	api-process-add.cpp \
	api-process-remove.cpp \
	api-transfer.cpp \
	$(END)

# NOTE: we cannot pass 'liburd_aux.la' directly to 'urd_LDFLAGS' as usual,
# because backends rely on the initialization of several static (and 
# unreferenced) variables to self-register, so that they can be automatically 
# constructed. Since they are not referenced elsewhere, the linker removes
# the variables, which makes the self-registering process not work. To avoid 
# this, we need to link the convenience library with '-Wl,--whole-archive'
# to force the inclusion of these symbols and then disable it with 
# '-Wl,--no-whole-archive'. Unfortunately, the order of flags
# cannot be controlled, which forces us to define it explicitly as
# '-Wl,--whole-archive,.libs/liburd_aux.a,--no-whole-archive' and to include
# several extra dependencies which would not be needed otherwise
api_LDFLAGS = \
	@TBB_LIBS@ \
    @BOOST_ASIO_LIB@ \
	@BOOST_LDFLAGS@	\
    @BOOST_PROGRAM_OPTIONS_LIB@	\
    @BOOST_SYSTEM_LIB@ \
    @BOOST_THREAD_LIB@ \
	@PROTOBUF_LIBS@ \
	-Wl,--whole-archive,$(top_builddir)/src/.libs/liburd_aux.a,--no-whole-archive \
	$(top_builddir)/lib/libnorns.la \
	$(END)

EXTRA_api_DEPENDENCIES = \
	$(top_builddir)/src/liburd_aux.la \
	$(top_builddir)/lib/libnorns.la \
	$(END)
+130 −0
Original line number Diff line number Diff line
/*************************************************************************
 * Copyright (C) 2017-2018 Barcelona Supercomputing Center               *
 *                         Centro Nacional de Supercomputacion           *
 *                                                                       *
 * This file is part of the Data Scheduler, a daemon for tracking and    *
 * managing requests for asynchronous data transfer in a hierarchical    *
 * storage environment.                                                  *
 *                                                                       *
 * See AUTHORS file in the top level directory for information           *
 * regarding developers and contributors.                                *
 *                                                                       *
 * The Data Scheduler is free software: you can redistribute it and/or   *
 * modify it under the terms of the GNU Lesser General Public License    *
 * as published by the Free Software Foundation, either version 3 of     *
 * the License, or (at your option) any later version.                   *
 *                                                                       *
 * The Data Scheduler is distributed in the hope that it will be useful, *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 * Lesser General Public License for more details.                       *
 *                                                                       *
 * You should have received a copy of the GNU Lesser General             *
 * Public License along with Data Scheduler.  If not, see                *
 * <http://www.gnu.org/licenses/>.                                       *
 *                                                                       *
 *************************************************************************/

#include "catch.hpp"

#include <chrono>
#include <norns.h>
#include <urd.hpp>
#include <settings.hpp>

SCENARIO("register job", "[api::norns_register_job]") {
    GIVEN("a running urd instance") {

        urd test_daemon;

        config_settings settings = {
            "test_urd", /* progname */
            true, /* daemonize */
            false, /* detach */
            "./", /* running_dir */
            "./test_urd.socket", /* api_sockfile */
            "./test_urd.pid", /* daemon_pidfile */
            2, /* api workers */
            "./",
            42,
            {}
        };

        test_daemon.configure(settings);
        test_daemon.run();
        extern const char* norns_api_sockfile;
        norns_api_sockfile = "./test_urd.socket";

        // wait some time for the daemon to prepare itself to receive requests
        std::this_thread::sleep_for(std::chrono::milliseconds(200));

        WHEN("a job is registered with invalid information") {

            struct norns_cred cred;
            struct norns_job job = NORNS_JOB_INIT(NULL, 0, NULL, 0);

            const uint32_t jobid = 42;

            int rv = norns_register_job(&cred, jobid, &job);

            THEN("NORNS_EBADARGS is returned") {
                REQUIRE(rv == NORNS_EBADARGS);
            }
        }

        WHEN("a job is registered with valid information") {

            const char* test_hosts[] = { "host00", "host01" };
            const size_t test_nhosts = sizeof(test_hosts) / sizeof(test_hosts[0]);

            struct norns_backend b0 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b0://", "/mnt/b0", 1024);
            struct norns_backend b1 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b1://", "/mnt/b1", 2048);
            struct norns_backend b2 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b2://", "/mnt/b2", 1024);

            struct norns_backend* test_backends[] = { &b0, &b1, &b2 };

            const size_t test_nbackends = sizeof(test_backends) / sizeof(test_backends[0]);

            struct norns_cred cred;
            struct norns_job job = NORNS_JOB_INIT(test_hosts, test_nhosts, test_backends, test_nbackends);

            const uint32_t jobid = 42;

            int rv = norns_register_job(&cred, jobid, &job);

            THEN("NORNS_SUCCESS is returned") {
                REQUIRE(rv == NORNS_SUCCESS);
            }
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        test_daemon.stop();
    }

    GIVEN("a non-running urd instance") {
        WHEN("attempting to register a job") {

            const char* test_hosts[] = { "host00", "host01" };
            const size_t test_nhosts = sizeof(test_hosts) / sizeof(test_hosts[0]);

            struct norns_backend b0 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b0://", "/mnt/b0", 1024);
            struct norns_backend b1 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b1://", "/mnt/b1", 2048);
            struct norns_backend b2 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b2://", "/mnt/b2", 1024);

            struct norns_backend* test_backends[] = { &b0, &b1, &b2 };

            const size_t test_nbackends = sizeof(test_backends) / sizeof(test_backends[0]);

            struct norns_cred cred;
            struct norns_job job = NORNS_JOB_INIT(test_hosts, test_nhosts, test_backends, test_nbackends);

            const uint32_t jobid = 42;

            int rv = norns_register_job(&cred, jobid, &job);

            THEN("NORNS_ECONNFAILED is returned") {
                REQUIRE(rv == NORNS_ECONNFAILED);
            }
        }
    }
}
+156 −0
Original line number Diff line number Diff line
/*************************************************************************
 * Copyright (C) 2017-2018 Barcelona Supercomputing Center               *
 *                         Centro Nacional de Supercomputacion           *
 *                                                                       *
 * This file is part of the Data Scheduler, a daemon for tracking and    *
 * managing requests for asynchronous data transfer in a hierarchical    *
 * storage environment.                                                  *
 *                                                                       *
 * See AUTHORS file in the top level directory for information           *
 * regarding developers and contributors.                                *
 *                                                                       *
 * The Data Scheduler is free software: you can redistribute it and/or   *
 * modify it under the terms of the GNU Lesser General Public License    *
 * as published by the Free Software Foundation, either version 3 of     *
 * the License, or (at your option) any later version.                   *
 *                                                                       *
 * The Data Scheduler is distributed in the hope that it will be useful, *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 * Lesser General Public License for more details.                       *
 *                                                                       *
 * You should have received a copy of the GNU Lesser General             *
 * Public License along with Data Scheduler.  If not, see                *
 * <http://www.gnu.org/licenses/>.                                       *
 *                                                                       *
 *************************************************************************/

#include "catch.hpp"

#include <chrono>
#include <norns.h>
#include <urd.hpp>
#include <settings.hpp>

SCENARIO("unregister job", "[api::norns_unregister_job]") {
    GIVEN("a running urd instance") {

        urd test_daemon;

        config_settings settings = {
            "test_urd", /* progname */
            true, /* daemonize */
            false, /* detach */
            "./", /* running_dir */
            "./test_urd.socket", /* api_sockfile */
            "./test_urd.pid", /* daemon_pidfile */
            2, /* api workers */
            "./",
            42,
            {}
        };

        test_daemon.configure(settings);
        test_daemon.run();
        extern const char* norns_api_sockfile;
        norns_api_sockfile = "./test_urd.socket";

        // wait some time for the daemon to prepare itself to receive requests
        std::this_thread::sleep_for(std::chrono::milliseconds(200));

        WHEN("a non-registered job is unregistered") {

            struct norns_cred cred;
            const uint32_t jobid = 42;

            int rv = norns_unregister_job(&cred, jobid);

            THEN("NORNS_ENOSUCHJOB is returned") {
                REQUIRE(rv == NORNS_ENOSUCHJOB);
            }
        }

        WHEN("a registered job is unregistered") {

            /* valid information for norns_register_job */
            const char* test_hosts[] = { "host00", "host01" };
            const size_t test_nhosts = sizeof(test_hosts) / sizeof(test_hosts[0]);

            struct norns_backend b0 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b0://", "/mnt/b0", 1024);
            struct norns_backend b1 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b1://", "/mnt/b1", 2048);
            struct norns_backend b2 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b2://", "/mnt/b2", 1024);

            struct norns_backend* test_backends[] = { &b0, &b1, &b2 };
            const size_t test_nbackends = sizeof(test_backends) / sizeof(test_backends[0]);

            struct norns_cred cred;
            struct norns_job job = NORNS_JOB_INIT(test_hosts, test_nhosts, test_backends, test_nbackends);
            const uint32_t jobid = 42;

            int rv = norns_register_job(&cred, jobid, &job);

            REQUIRE(rv == NORNS_SUCCESS);

            rv = norns_unregister_job(&cred, jobid);

            THEN("NORNS_SUCCESS is returned") {
                REQUIRE(rv == NORNS_SUCCESS);
            }
        }

        WHEN("a registered job is updated and unregistered") {

            /* valid information for norns_register_job */
            const char* test_hosts1[] = { "host00", "host01" };
            const char* test_hosts2[] = { "host02", "host03", "host04" };
            const size_t test_nhosts1 = sizeof(test_hosts1) / sizeof(test_hosts1[0]);
            const size_t test_nhosts2 = sizeof(test_hosts2) / sizeof(test_hosts2[0]);

            struct norns_backend b0 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b0://", "/mnt/b0", 1024);
            struct norns_backend b1 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b1://", "/mnt/b1", 2048);
            struct norns_backend b2 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b2://", "/mnt/b2", 1024);
            struct norns_backend b3 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b3://", "/mnt/b3", 3072);

            struct norns_backend* test_backends1[] = { &b0, &b1, &b2 };
            const size_t test_nbackends1 = sizeof(test_backends1) / sizeof(test_backends1[0]);
            struct norns_backend* test_backends2[] = { &b1, &b2, &b3 };
            const size_t test_nbackends2 = sizeof(test_backends2) / sizeof(test_backends2[0]);

            struct norns_job job1 = NORNS_JOB_INIT(test_hosts1, test_nhosts1, test_backends1, test_nbackends1);
            struct norns_job job2 = NORNS_JOB_INIT(test_hosts2, test_nhosts2, test_backends2, test_nbackends2);
            struct norns_cred cred;
            const uint32_t jobid = 42;

            int rv = norns_register_job(&cred, jobid, &job1);

            REQUIRE(rv == NORNS_SUCCESS);

            rv = norns_update_job(&cred, jobid, &job2);

            REQUIRE(rv == NORNS_SUCCESS);

            rv = norns_unregister_job(&cred, jobid);

            THEN("NORNS_SUCCESS is returned") {
                REQUIRE(rv == NORNS_SUCCESS);
            }
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        test_daemon.stop();
    }

    GIVEN("a non-running urd instance") {
        WHEN("attempting to unregister a job") {

            struct norns_cred cred;
            const uint32_t jobid = 42;

            int rv = norns_unregister_job(&cred, jobid);

            THEN("NORNS_ECONNFAILED is returned") {
                REQUIRE(rv == NORNS_ECONNFAILED);
            }
        }
    }
}
+191 −0
Original line number Diff line number Diff line
/*************************************************************************
 * Copyright (C) 2017-2018 Barcelona Supercomputing Center               *
 *                         Centro Nacional de Supercomputacion           *
 *                                                                       *
 * This file is part of the Data Scheduler, a daemon for tracking and    *
 * managing requests for asynchronous data transfer in a hierarchical    *
 * storage environment.                                                  *
 *                                                                       *
 * See AUTHORS file in the top level directory for information           *
 * regarding developers and contributors.                                *
 *                                                                       *
 * The Data Scheduler is free software: you can redistribute it and/or   *
 * modify it under the terms of the GNU Lesser General Public License    *
 * as published by the Free Software Foundation, either version 3 of     *
 * the License, or (at your option) any later version.                   *
 *                                                                       *
 * The Data Scheduler is distributed in the hope that it will be useful, *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 * Lesser General Public License for more details.                       *
 *                                                                       *
 * You should have received a copy of the GNU Lesser General             *
 * Public License along with Data Scheduler.  If not, see                *
 * <http://www.gnu.org/licenses/>.                                       *
 *                                                                       *
 *************************************************************************/

#include "catch.hpp"

#include <chrono>
#include <norns.h>
#include <urd.hpp>
#include <settings.hpp>

SCENARIO("update job", "[api::norns_update_job]") {
    GIVEN("a running urd instance") {

        urd test_daemon;

        config_settings settings = {
            "test_urd", /* progname */
            true, /* daemonize */
            false, /* detach */
            "./", /* running_dir */
            "./test_urd.socket", /* api_sockfile */
            "./test_urd.pid", /* daemon_pidfile */
            2, /* api workers */
            "./",
            42,
            {}
        };

        test_daemon.configure(settings);
        test_daemon.run();
        extern const char* norns_api_sockfile;
        norns_api_sockfile = "./test_urd.socket";

        // wait some time for the daemon to prepare itself to receive requests
        std::this_thread::sleep_for(std::chrono::milliseconds(200));

        WHEN("a non-registered job is updated with invalid information") {

            struct norns_cred cred;
            struct norns_job job = NORNS_JOB_INIT(NULL, 0, NULL, 0);
            const uint32_t jobid = 42;

            int rv = norns_update_job(&cred, jobid, &job);

            THEN("NORNS_EBADARGS is returned") {
                REQUIRE(rv == NORNS_EBADARGS);
            }
        }

        WHEN("a non-registered job is updated with valid information") {

            const char* test_hosts[] = { "host00", "host01" };
            const size_t test_nhosts = sizeof(test_hosts) / sizeof(test_hosts[0]);

            struct norns_backend b0 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b0://", "/mnt/b0", 1024);
            struct norns_backend b1 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b1://", "/mnt/b1", 2048);
            struct norns_backend b2 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b2://", "/mnt/b2", 1024);

            struct norns_backend* test_backends[] = { &b0, &b1, &b2 };
            const size_t test_nbackends = sizeof(test_backends) / sizeof(test_backends[0]);

            struct norns_cred cred;
            struct norns_job job = NORNS_JOB_INIT(test_hosts, test_nhosts, test_backends, test_nbackends);
            const uint32_t jobid = 42;

            int rv = norns_update_job(&cred, jobid, &job);

            THEN("NORNS_ENOSUCHJOB is returned") {
                REQUIRE(rv == NORNS_ENOSUCHJOB);
            }
        }

        WHEN("a registered job is updated with invalid information") {

            /* valid information for norns_register_job */
            const char* test_hosts[] = { "host00", "host01" };
            const size_t test_nhosts = sizeof(test_hosts) / sizeof(test_hosts[0]);

            struct norns_backend b0 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b0://", "/mnt/b0", 1024);
            struct norns_backend b1 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b1://", "/mnt/b1", 2048);
            struct norns_backend b2 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b2://", "/mnt/b2", 1024);

            struct norns_backend* test_backends[] = { &b0, &b1, &b2 };
            const size_t test_nbackends = sizeof(test_backends) / sizeof(test_backends[0]);

            struct norns_cred cred;
            struct norns_job job1 = NORNS_JOB_INIT(test_hosts, test_nhosts, test_backends, test_nbackends);
            struct norns_job job2 = NORNS_JOB_INIT(NULL, 0, NULL, 0);
            const uint32_t jobid = 42;

            int rv = norns_register_job(&cred, jobid, &job1);

            REQUIRE(rv == NORNS_SUCCESS);

            rv = norns_update_job(&cred, jobid, &job2);

            THEN("NORNS_EBADARGS is returned") {
                REQUIRE(rv == NORNS_EBADARGS);
            }
        }

        WHEN("a registered job is updated with valid information") {

            /* valid information for norns_register_job */
            const char* test_hosts1[] = { "host00", "host01" };
            const char* test_hosts2[] = { "host02", "host03", "host04" };
            const size_t test_nhosts1 = sizeof(test_hosts1) / sizeof(test_hosts1[0]);
            const size_t test_nhosts2 = sizeof(test_hosts2) / sizeof(test_hosts2[0]);

            struct norns_backend b0 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b0://", "/mnt/b0", 1024);
            struct norns_backend b1 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b1://", "/mnt/b1", 2048);
            struct norns_backend b2 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b2://", "/mnt/b2", 1024);
            struct norns_backend b3 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b3://", "/mnt/b3", 3072);

            struct norns_backend* test_backends1[] = { &b0, &b1, &b2 };
            const size_t test_nbackends1 = sizeof(test_backends1) / sizeof(test_backends1[0]);
            struct norns_backend* test_backends2[] = { &b1, &b2, &b3 };
            const size_t test_nbackends2 = sizeof(test_backends2) / sizeof(test_backends2[0]);

            struct norns_job job1 = NORNS_JOB_INIT(test_hosts1, test_nhosts1, test_backends1, test_nbackends1);
            struct norns_job job2 = NORNS_JOB_INIT(test_hosts2, test_nhosts2, test_backends2, test_nbackends2);
            struct norns_cred cred;
            const uint32_t jobid = 42;

            int rv = norns_register_job(&cred, jobid, &job1);

            REQUIRE(rv == NORNS_SUCCESS);

            rv = norns_update_job(&cred, jobid, &job2);

            THEN("NORNS_SUCCESS is returned") {
                REQUIRE(rv == NORNS_SUCCESS);
            }
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(200));

        test_daemon.stop();
    }

    GIVEN("a non-running urd instance") {
        WHEN("attempting to update a job") {

            const char* test_hosts[] = { "host00", "host01" };
            const size_t test_nhosts = sizeof(test_hosts) / sizeof(test_hosts[0]);

            struct norns_backend b0 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b0://", "/mnt/b0", 1024);
            struct norns_backend b1 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b1://", "/mnt/b1", 2048);
            struct norns_backend b2 = NORNS_BACKEND_INIT(NORNS_BACKEND_LOCAL_NVML, "b2://", "/mnt/b2", 1024);

            struct norns_backend* test_backends[] = { &b0, &b1, &b2 };

            const size_t test_nbackends = sizeof(test_backends) / sizeof(test_backends[0]);

            struct norns_cred cred;
            struct norns_job job = NORNS_JOB_INIT(test_hosts, test_nhosts, test_backends, test_nbackends);

            const uint32_t jobid = 42;

            int rv = norns_update_job(&cred, jobid, &job);

            THEN("NORNS_ECONNFAILED is returned") {
                REQUIRE(rv == NORNS_ECONNFAILED);
            }
        }
    }
}

tests/api-main.cpp

0 → 100644
+29 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading