diff --git a/.gitignore b/.gitignore
index 9a1737c1493a8adfe682ebb8418e14ff97685972..bdb7e7fa8ac6a490ce962d3b58d211e09d7b0cf7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,3 +16,4 @@ config.log
src/old-sources
src/spdlog_0.12/
build
+build.*
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e0270e18a960fd95e5fb54524fc4b0282f62e930..ac051b7f888b5b55fb31852836f6179975425abd 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -209,9 +209,9 @@ test:coverage:
- NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./core -as
- make -j$(nproc) api
- NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./api -as "[api::NORNS_TASK]"
+ - NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./api -as "[api::norns_error]"
- NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./api -as "[api::norns_iotask_init]"
- NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./api -as "[api::norns_resource_init]"
- - NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./api -as "[api::norns_status]"
- NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./api -as "[api::norns_submit]"
- NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./api -as "[api::norns_submit_copy_buffer_to_file]"
- NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./api -as "[api::norns_submit_copy_local_posix_files]"
@@ -325,9 +325,9 @@ test:optimized:
- NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./core -as
- make -j$(nproc) api
- NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./api -as "[api::NORNS_TASK]"
+ - NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./api -as "[api::norns_error]"
- NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./api -as "[api::norns_iotask_init]"
- NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./api -as "[api::norns_resource_init]"
- - NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./api -as "[api::norns_status]"
- NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./api -as "[api::norns_submit]"
- NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./api -as "[api::norns_submit_copy_buffer_to_file]"
- NORNS_DEBUG_CONFIG_FILE_OVERRIDE=1 ./api -as "[api::norns_submit_copy_local_posix_files]"
diff --git a/include/Makefile.am b/include/Makefile.am
index fdbdcd64deb1fa0c272db04344d3fe4db17a2447..633bbef2667d866665b6a283b1bbaf13124deece 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -32,10 +32,8 @@ nornsincludedir=$(includedir)/norns
nornsinclude_HEADERS = \
norns/norns.h \
norns/nornsctl.h \
- norns/norns_backends.h \
norns/norns_debug.h \
norns/norns_error.h \
- norns/norns_resources.h \
norns/norns_types.h
include_HEADERS = \
diff --git a/include/norns/norns.h b/include/norns/norns.h
index 6cc982e67cab93993b8d8d232678e62ce2e9982e..cb0bcffc0718a990aa396e2404fc599beb8a1dff 100644
--- a/include/norns/norns.h
+++ b/include/norns/norns.h
@@ -38,8 +38,6 @@
#include "norns_types.h"
#include "norns_error.h"
-#include "norns_backends.h"
-#include "norns_resources.h"
#ifdef __NORNS_DEBUG__
#include "norns_debug.h"
@@ -49,51 +47,37 @@
extern "C" {
#endif
-
-/* Descriptor for an I/O task */
-typedef struct {
- norns_tid_t t_id; /* task identifier */
- norns_op_t t_op; /* operation to be performed */
- norns_resource_t t_src; /* source resource */
- norns_resource_t t_dst; /* destination resource */
-} norns_iotask_t;
-
-/* Task types */
-#define NORNS_IOTASK_COPY 0x1
-#define NORNS_IOTASK_MOVE 0x2
-#define NORNS_IOTASK_REMOVE 0x3
-
-/* I/O task status descriptor */
-typedef struct {
- norns_status_t st_status; /* task current status */
- norns_error_t st_task_error; /* task return value */
- int st_sys_errno; /* errno returned if st_task_error == NORNS_ESYSTEM_ERROR */
- size_t st_pending; /* bytes pending in task */
- size_t st_total; /* total bytes in task */
-} norns_stat_t;
-
/**************************************************************************/
/* Client API */
/**************************************************************************/
/* Initialize an asynchronous I/O task */
-void norns_iotask_init(norns_iotask_t* task, norns_op_t operation,
- norns_resource_t* src, norns_resource_t* dst) __THROW;
+void
+norns_iotask_init(norns_iotask_t* task,
+ norns_op_t operation,
+ norns_resource_t* src,
+ norns_resource_t* dst) __THROW;
norns_iotask_t
-NORNS_IOTASK(norns_op_t operation, norns_resource_t src, ...) __THROW;
+NORNS_IOTASK(norns_op_t operation,
+ norns_resource_t src, ...) __THROW;
/* Submit an asynchronous I/O task */
-norns_error_t norns_submit(norns_iotask_t* task) __THROW;
+norns_error_t
+norns_submit(norns_iotask_t* task) __THROW;
/* wait for the completion of the I/O task associated to 'task' */
-norns_error_t norns_wait(norns_iotask_t* task) __THROW;
+norns_error_t
+norns_wait(norns_iotask_t* task) __THROW;
/* Try to cancel an asynchronous I/O task associated with task */
-norns_error_t norns_cancel(norns_iotask_t* task) __THROW;
+norns_error_t
+norns_cancel(norns_iotask_t* task) __THROW;
/* Check the status of a submitted I/O task */
-norns_error_t norns_status(norns_iotask_t* task, norns_stat_t* stats) __THROW;
+norns_error_t
+norns_error(norns_iotask_t* task,
+ norns_stat_t* stats) __THROW;
/* Return a string describing the error number */
char* norns_strerror(norns_error_t errnum) __THROW;
diff --git a/include/norns/norns_backends.h b/include/norns/norns_backends.h
deleted file mode 100644
index 3eca26da948d0d5abdaf305b2aa784a3a995035b..0000000000000000000000000000000000000000
--- a/include/norns/norns_backends.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*************************************************************************
- * Copyright (C) 2017-2018 Barcelona Supercomputing Center *
- * Centro Nacional de Supercomputacion *
- * All rights reserved. *
- * *
- * This file is part of the NORNS Data Scheduler, a service that allows *
- * other programs to start, track and manage asynchronous transfers of *
- * data resources transfers requests between different storage backends. *
- * *
- * See AUTHORS file in the top level directory for information *
- * regarding developers and contributors. *
- * *
- * The NORNS 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 NORNS 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 the NORNS Data Scheduler. If not, see *
- * . *
- *************************************************************************/
-
-#ifndef __NORNS_BACKENDS_H__
-#define __NORNS_BACKENDS_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Storage backend types */
-//#define NORNS_BACKEND_LOCAL_NVML 0x10000000
-//#define NORNS_BACKEND_REMOTE_NVML 0x10000001
-//#define NORNS_BACKEND_PROCESS_MEMORY 0x10000005 // deprecated
-#define NORNS_BACKEND_NVML 0x10000001
-#define NORNS_BACKEND_LUSTRE 0x10000002
-#define NORNS_BACKEND_ECHOFS 0x10000003
-#define NORNS_BACKEND_POSIX_FILESYSTEM 0x10000004
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __NORNS_BACKENDS_H__ */
diff --git a/include/norns/norns_resources.h b/include/norns/norns_resources.h
deleted file mode 100644
index 35ff4b94aa29a3443e970597e2c231dead9c0e9a..0000000000000000000000000000000000000000
--- a/include/norns/norns_resources.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*************************************************************************
- * Copyright (C) 2017-2018 Barcelona Supercomputing Center *
- * Centro Nacional de Supercomputacion *
- * All rights reserved. *
- * *
- * This file is part of the NORNS Data Scheduler, a service that allows *
- * other programs to start, track and manage asynchronous transfers of *
- * data resources transfers requests between different storage backends. *
- * *
- * See AUTHORS file in the top level directory for information *
- * regarding developers and contributors. *
- * *
- * The NORNS 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 NORNS 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 the NORNS Data Scheduler. If not, see *
- * . *
- *************************************************************************/
-
-#ifndef __NORNS_RESOURCES_H__
-#define __NORNS_RESOURCES_H__ 1
-
-#include
-#include
-#include /* For uint32_t et al. */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Resource types */
-#define NORNS_PROCESS_MEMORY 0x0100000 /* Memory buffer */
-#define NORNS_POSIX_PATH 0x0200000 /* POSIX path */
-#define NORNS_NULL_RESOURCE 0x1000000
-
-/* Access types */
-#define R_LOCAL 0x0000010 /* Local resource (default) */
-#define R_REMOTE 0x0000020 /* Remote resource */
-#define R_SHARED 0x0000040 /* Shared resource */
-
-/* Descriptor for a memory region */
-typedef struct {
- void* b_addr; /* base memory address */
- size_t b_size; /* region size */
-} norns_memory_region_t;
-
-/* Descriptor for a POSIX path */
-typedef struct {
- const char* p_nsid; /* namespace id */
- const char* p_host; /* hostname (NULL if local) */
- const char* p_path; /* path to "data" (i.e. file or directory) */
-} norns_posix_path_t;
-
-/* Data resource descriptor */
-typedef struct {
-
- // options:
- // - read from local nvm and write to lustre
- // - read from lustre and write to local nvm
- // - read from remote nvm and write to local nvm
- // - read from local nvm and write to remote nvm
- // - read from process memory and write to local nvm
- // - read from process memory and write to lustre
- // - echofs: "read" from lustre into echofs
- // - echofs: "write" from echofs to lustre
- //
- //
- // - NEXTGenIO input resources:
- // 1. local nvm nvm://path/to/dir/[file] DAX-NVML
- // 2. local tmpfs tmpfs://path/to/dir/[file] DAX-NVML
- // 3. lustre lustre://path/to/dir/[file] POSIX
- // 4. remote nvm nvm@hostname://path/to/dir/[file] DAX-NVML+RDMA/TCP
- // 5. echofs echofs://path/to/dir/[file] CUSTOM
- // 6. process memory [pointer + size] MEMORY
- //
- // - NEXTGenIO output resources:
- // 1. local nvm nvm://path/to/dir/[file] DAX-NVML
- // 2. local tmpfs tmpfs://path/to/dir/[file] DAX-NVML
- // 3. lustre (path) lustre://path/to/dir/[file] POSIX
- // 4. remote nvm nvm@hostname:://path/to/dir/[file] DAX-NVML+RDMA/TCP
- // 5. echofs echofs://path/to/dir/[file] CUSTOM
-
- norns_flags_t r_flags; /* resource type and flags */
- union {
- norns_memory_region_t r_buffer;
- norns_posix_path_t r_posix_path;
- };
-} norns_resource_t;
-
-norns_resource_t NORNS_MEMORY_REGION(void* addr, size_t size);
-norns_resource_t NORNS_LOCAL_PATH(const char* nsid, const char* path);
-norns_resource_t NORNS_REMOTE_PATH(const char* nsid, const char* host, const char* path);
-norns_resource_t NORNS_SHARED_PATH(const char* nsid, const char* path);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __NORNS_RESOURCES_H__ */
diff --git a/include/norns/norns_types.h b/include/norns/norns_types.h
index d42a3963e9844d1052a3385739b358fa78777504..683d8acd391c6025b2ccc5e3868e38ad8ee6012a 100644
--- a/include/norns/norns_types.h
+++ b/include/norns/norns_types.h
@@ -28,17 +28,138 @@
#ifndef __NORNS_TYPES_H__
#define __NORNS_TYPES_H__ 1
+#include
+#include /* For uint32_t et al. */
+#include
+
#ifdef __cplusplus
extern "C" {
#endif
/* Types */
typedef uint32_t norns_tid_t;
-typedef uint32_t norns_op_t;
typedef uint32_t norns_flags_t;
typedef int32_t norns_status_t;
typedef int32_t norns_error_t;
+/* Resource types */
+#define NORNS_PROCESS_MEMORY 0x0100000 /* Memory buffer */
+#define NORNS_POSIX_PATH 0x0200000 /* POSIX path */
+#define NORNS_NULL_RESOURCE 0x1000000
+
+/* Access types */
+#define R_LOCAL 0x0000010 /* Local resource (default) */
+#define R_REMOTE 0x0000020 /* Remote resource */
+#define R_SHARED 0x0000040 /* Shared resource */
+
+/* Descriptor for a memory region */
+typedef struct {
+ void* b_addr; /* base memory address */
+ size_t b_size; /* region size */
+} norns_memory_region_t;
+
+/* Descriptor for a POSIX path */
+typedef struct {
+ const char* p_nsid; /* namespace id */
+ const char* p_host; /* hostname (NULL if local) */
+ const char* p_path; /* path to "data" (i.e. file or directory) */
+} norns_posix_path_t;
+
+/* Data resource descriptor */
+typedef struct {
+
+ // options:
+ // - read from local nvm and write to lustre
+ // - read from lustre and write to local nvm
+ // - read from remote nvm and write to local nvm
+ // - read from local nvm and write to remote nvm
+ // - read from process memory and write to local nvm
+ // - read from process memory and write to lustre
+ // - echofs: "read" from lustre into echofs
+ // - echofs: "write" from echofs to lustre
+ //
+ //
+ // - NEXTGenIO input resources:
+ // 1. local nvm nvm://path/to/dir/[file] DAX-NVML
+ // 2. local tmpfs tmpfs://path/to/dir/[file] DAX-NVML
+ // 3. lustre lustre://path/to/dir/[file] POSIX
+ // 4. remote nvm nvm@hostname://path/to/dir/[file] DAX-NVML+RDMA/TCP
+ // 5. echofs echofs://path/to/dir/[file] CUSTOM
+ // 6. process memory [pointer + size] MEMORY
+ //
+ // - NEXTGenIO output resources:
+ // 1. local nvm nvm://path/to/dir/[file] DAX-NVML
+ // 2. local tmpfs tmpfs://path/to/dir/[file] DAX-NVML
+ // 3. lustre (path) lustre://path/to/dir/[file] POSIX
+ // 4. remote nvm nvm@hostname:://path/to/dir/[file] DAX-NVML+RDMA/TCP
+ // 5. echofs echofs://path/to/dir/[file] CUSTOM
+
+ norns_flags_t r_flags; /* resource type and flags */
+ union {
+ norns_memory_region_t r_buffer;
+ norns_posix_path_t r_posix_path;
+ };
+} norns_resource_t;
+
+norns_resource_t
+NORNS_MEMORY_REGION(void* addr,
+ size_t size);
+
+norns_resource_t
+NORNS_LOCAL_PATH(const char* nsid,
+ const char* path);
+
+norns_resource_t
+NORNS_REMOTE_PATH(const char* nsid,
+ const char* host,
+ const char* path);
+
+norns_resource_t
+NORNS_SHARED_PATH(const char* nsid,
+ const char* path);
+
+/* Task types */
+typedef enum {
+ NORNS_IOTASK_COPY = 0x1,
+ NORNS_IOTASK_MOVE = 0x2,
+ NORNS_IOTASK_REMOVE = 0x3
+} norns_op_t;
+
+/* Descriptor for an I/O task */
+typedef struct {
+ norns_tid_t t_id; /* task identifier */
+ norns_op_t t_op; /* operation to be performed */
+ norns_resource_t t_src; /* source resource */
+ norns_resource_t t_dst; /* destination resource */
+} norns_iotask_t;
+
+/* I/O task status descriptor */
+typedef struct {
+ norns_status_t st_status; /* task current status */
+ norns_error_t st_task_error; /* task return value */
+ int st_sys_errno; /* errno returned if st_task_error == NORNS_ESYSTEM_ERROR */
+ size_t st_pending; /* bytes pending in task */
+ size_t st_total; /* total bytes in task */
+} norns_stat_t;
+
+
+
+/* Additional administrative types */
+typedef enum {
+ NORNS_BACKEND_NVML = 0x10000001,
+ NORNS_BACKEND_LUSTRE = 0x10000002,
+ NORNS_BACKEND_ECHOFS = 0x10000003,
+ NORNS_BACKEND_POSIX_FILESYSTEM = 0x10000004
+} nornsctl_backend_flags_t;
+
+/* Administrative command IDs valid for nornsctl_send_command() */
+typedef enum {
+ NORNSCTL_CMD_PING = 1000,
+ NORNSCTL_CMD_PAUSE_LISTEN,
+ NORNSCTL_CMD_RESUME_LISTEN,
+ NORNSCTL_CMD_SHUTDOWN,
+} nornsctl_command_t;
+
#ifdef __cplusplus
};
#endif
diff --git a/include/norns/nornsctl.h b/include/norns/nornsctl.h
index 552ff97745b43076b387007719a21d412eac1121..6333454b60fd4602cd855c802b785541ac850b53 100644
--- a/include/norns/nornsctl.h
+++ b/include/norns/nornsctl.h
@@ -32,9 +32,7 @@
#define NORNSCTL_API_VERSION 10
#endif
-#include
-#include
-#include "nornsctl_types.h"
+#include "norns_types.h"
#include "norns_error.h"
#ifdef __NORNS_DEBUG__
@@ -175,6 +173,35 @@ nornsctl_update_namespace(const char* nsid,
norns_error_t
nornsctl_unregister_namespace(const char* nsid) __THROW;
+
+/* Initialize an asynchronous I/O task */
+void
+nornsctl_iotask_init(norns_iotask_t* task,
+ norns_op_t operation,
+ norns_resource_t* src,
+ norns_resource_t* dst) __THROW;
+norns_iotask_t
+NORNSCTL_IOTASK(norns_op_t operation,
+ norns_resource_t src, ...) __THROW;
+
+
+/* Submit an asynchronous I/O task */
+norns_error_t
+nornsctl_submit(norns_iotask_t* task) __THROW;
+
+/* wait for the completion of the I/O task associated to 'task' */
+norns_error_t
+nornsctl_wait(norns_iotask_t* task) __THROW;
+
+/* Try to cancel an asynchronous I/O task associated with task */
+norns_error_t
+nornsctl_cancel(norns_iotask_t* task) __THROW;
+
+/* Check the status of a submitted I/O task */
+norns_error_t
+nornsctl_error(norns_iotask_t* task,
+ norns_stat_t* stats) __THROW;
+
/* Return a string describing the error number */
char*
nornsctl_strerror(norns_error_t errnum) __THROW;
diff --git a/include/norns/nornsctl_types.h b/include/norns/nornsctl_types.h
deleted file mode 100644
index f5aa133155e7ae213b5aa0b4d48c22c73a00568c..0000000000000000000000000000000000000000
--- a/include/norns/nornsctl_types.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*************************************************************************
- * Copyright (C) 2017-2018 Barcelona Supercomputing Center *
- * Centro Nacional de Supercomputacion *
- * All rights reserved. *
- * *
- * This file is part of the NORNS Data Scheduler, a service that allows *
- * other programs to start, track and manage asynchronous transfers of *
- * data resources transfers requests between different storage backends. *
- * *
- * See AUTHORS file in the top level directory for information *
- * regarding developers and contributors. *
- * *
- * The NORNS 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 NORNS 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 the NORNS Data Scheduler. If not, see *
- * . *
- *************************************************************************/
-
-#ifndef __NORNSCTL_TYPES_H__
-#define __NORNSCTL_TYPES_H__ 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "norns_types.h"
-
-/* Additional administrative types */
-typedef uint32_t nornsctl_backend_flags_t;
-//typedef uint32_t nornsctl_command_t;
-
-/* Administrative command IDs valid for nornsctl_send_command() */
-typedef enum {
- NORNSCTL_CMD_PING = 1000,
- NORNSCTL_CMD_PAUSE_LISTEN,
- NORNSCTL_CMD_RESUME_LISTEN,
- NORNSCTL_CMD_SHUTDOWN,
-} nornsctl_command_t;
-
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif /* __NORNSCTL_TYPES_H__ */
diff --git a/lib/libnorns.c b/lib/libnorns.c
index da4fd57ba90642a460498386f971734328638232..ed8de57932721c6160977bd7c68197d96fe85717 100644
--- a/lib/libnorns.c
+++ b/lib/libnorns.c
@@ -204,7 +204,7 @@ norns_submit(norns_iotask_t* task) {
}
norns_error_t
-norns_status(norns_iotask_t* task, norns_stat_t* stats) {
+norns_error(norns_iotask_t* task, norns_stat_t* stats) {
if(task == NULL || stats == NULL) {
return NORNS_EBADARGS;
diff --git a/lib/libnornsctl.c b/lib/libnornsctl.c
index d2bd5e153b9c95204de812aff78e3da5487fb60a..0e7c03d060846d84720d0942d6198e3754439cf9 100644
--- a/lib/libnornsctl.c
+++ b/lib/libnornsctl.c
@@ -45,6 +45,7 @@
#include "defaults.h"
#define LIBNORNSCTL_LOG_PREFIX "libnornsctl"
+#define MIN_WAIT_TIME ((useconds_t) 250*1e3)
static bool validate_job(nornsctl_job_t* job);
static bool validate_namespace(nornsctl_backend_t* backend);
@@ -331,6 +332,108 @@ nornsctl_job_init(nornsctl_job_t* job, const char** hosts, size_t nhosts,
job->j_nlimits = nlimits;
}
+norns_iotask_t
+NORNSCTL_IOTASK(norns_op_t optype, norns_resource_t src, ...) {
+ norns_iotask_t task;
+
+ if(optype == NORNS_IOTASK_REMOVE) {
+ nornsctl_iotask_init(&task, optype, &src, NULL);
+ return task;
+ }
+
+ va_list ap;
+ va_start(ap, src);
+ norns_resource_t dst = va_arg(ap, norns_resource_t);
+ nornsctl_iotask_init(&task, optype, &src, &dst);
+ va_end(ap);
+
+ return task;
+}
+
+void
+nornsctl_iotask_init(norns_iotask_t* task,
+ norns_op_t optype,
+ norns_resource_t* src,
+ norns_resource_t* dst) {
+
+ if(task == NULL) {
+ return;
+ }
+
+ memset(task, 0, sizeof(*task));
+
+ if(src == NULL) {
+ return;
+ }
+
+ task->t_id = 0;
+ task->t_op = optype;
+ task->t_src = *src;
+
+ if(dst != NULL) {
+ task->t_dst = *dst;
+ return;
+ }
+
+ // dst is NULL, set r_flags so that we are aware of it later
+ task->t_dst.r_flags = NORNS_NULL_RESOURCE;
+}
+
+norns_error_t
+nornsctl_submit(norns_iotask_t* task) {
+
+ if(task == NULL) {
+ return NORNS_EBADARGS;
+ }
+
+ return send_submit_request(task);
+}
+
+norns_error_t
+nornsctl_error(norns_iotask_t* task,
+ norns_stat_t* stats) {
+
+ if(task == NULL || stats == NULL) {
+ return NORNS_EBADARGS;
+ }
+
+ return send_status_request(task, stats);
+}
+
+/* wait for the completion of the I/O task associated to 'task' */
+norns_error_t
+nornsctl_wait(norns_iotask_t* task) {
+
+ norns_error_t rv;
+ norns_stat_t stats;
+
+ if(task == NULL) {
+ ERR("invalid arguments");
+ return NORNS_EBADARGS;
+ }
+
+ do {
+ rv = send_status_request(task, &stats);
+
+ if(rv != NORNS_SUCCESS) {
+ ERR("error waiting for request: %s", norns_strerror(rv));
+ return rv;
+ }
+
+ if(stats.st_status == NORNS_EFINISHED ||
+ stats.st_status == NORNS_EFINISHEDWERROR) {
+ return NORNS_SUCCESS;
+ }
+
+ // wait for 250 milliseconds
+ // before retrying
+ usleep(MIN_WAIT_TIME);
+ } while(true);
+
+ return NORNS_SUCCESS;
+}
+
+
static bool
validate_namespace(nornsctl_backend_t* backend) {
diff --git a/src/backends/posix-fs.hpp b/src/backends/posix-fs.hpp
index 5e558b87b4eadbb0a67bd0e24f736c9086b1d472..b631e8bce00e249a85dc8c60df0f8f85c694a7d6 100644
--- a/src/backends/posix-fs.hpp
+++ b/src/backends/posix-fs.hpp
@@ -31,7 +31,6 @@
#include
#include
-#include "norns/norns_backends.h"
#include "backend-base.hpp"
namespace bfs = boost::filesystem;
diff --git a/src/backends/process-memory.hpp b/src/backends/process-memory.hpp
index 9db0236b87e5644562d4ebb52dea6282b5831168..8db45700b294ebab287feb7f0c07a15e655dafff 100644
--- a/src/backends/process-memory.hpp
+++ b/src/backends/process-memory.hpp
@@ -31,7 +31,6 @@
#include
#include
-#include "norns/norns_backends.h"
#include "backend-base.hpp"
namespace bfs = boost::filesystem;
diff --git a/src/io/task-manager.cpp b/src/io/task-manager.cpp
index 6a1e4f40f6567ccfac2bb81c5714a1a4b0838670..c92b8ded442d00b4c030e662f60ea2d2f35b6fed 100644
--- a/src/io/task-manager.cpp
+++ b/src/io/task-manager.cpp
@@ -175,11 +175,13 @@ task_manager::create_task(iotask_type type,
return it->second;
}();
- // helper lambda to register the completion of tasks so that we can keep track
- // of the consumed bandwidth by each task
- // N.B: we use capture-by-value here so that the task_info_ptr is valid when
- // the callback is invoked.
- const auto register_completion = [=]() {
+ auto self(std::enable_shared_from_this::shared_from_this());
+
+ // helper lambda to register the completion of tasks so that we can keep
+ // track of the consumed bandwidth by each task
+ // N.B: we capture self and task_info_ptr (both shared_ptrs) by value to
+ // make sure that they will still be alive when the callback is invoked.
+ const auto register_completion = [self, task_info_ptr]() {
assert(task_info_ptr->status() == task_status::finished ||
task_info_ptr->status() == task_status::finished_with_error);
@@ -194,12 +196,12 @@ task_manager::create_task(iotask_type type,
const auto key = std::make_pair(task_info_ptr->src_rinfo()->nsid(),
task_info_ptr->dst_rinfo()->nsid());
- if(!m_bandwidth_backlog.count(key)) {
- m_bandwidth_backlog.emplace(key,
- boost::circular_buffer(m_backlog_size));
+ if(!self->m_bandwidth_backlog.count(key)) {
+ self->m_bandwidth_backlog.emplace(key,
+ boost::circular_buffer(self->m_backlog_size));
}
- m_bandwidth_backlog.at(key).push_back(bw);
+ self->m_bandwidth_backlog.at(key).push_back(bw);
}
};
diff --git a/src/io/task-manager.hpp b/src/io/task-manager.hpp
index 36a10c7d795e29280da2f7c3c67361e14d705637..03bce143709da92f0198f032fa59a15df4685612 100644
--- a/src/io/task-manager.hpp
+++ b/src/io/task-manager.hpp
@@ -50,7 +50,7 @@ enum class task_status;
struct task_stats;
struct task_info;
-struct task_manager {
+struct task_manager : public std::enable_shared_from_this {
struct pair_hash {
template
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 8de929bd3902425cc42bff9b69aaa02e7cb37dd3..9122ac0791d8275386e30b83f5efe7242bb0da5c 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -63,6 +63,12 @@ api_SOURCES = \
api-task-submit.cpp \
api-task-status.cpp \
api-send-command.cpp \
+ api-ctl-copy-local-data.cpp \
+ api-ctl-task-init.cpp \
+ api-ctl-task-submit.cpp \
+ api-ctl-task-status.cpp \
+ api-ctl-copy-remote-data.cpp \
+ api-ctl-remove-local-data.cpp \
compare-files.cpp \
compare-files.hpp \
config-template.cpp \
diff --git a/tests/api-copy-local-data.cpp b/tests/api-copy-local-data.cpp
index c7a495fb1b6f45362fef705cea7d3004a0737a95..1e99cf974f4d47dcae1884e3a8c0f65c27ea7f0e 100644
--- a/tests/api-copy-local-data.cpp
+++ b/tests/api-copy-local-data.cpp
@@ -26,14 +26,14 @@
*************************************************************************/
#include "norns.h"
-#include "nornsctl.h"
#include "test-env.hpp"
#include "compare-files.hpp"
#include "catch.hpp"
namespace bfs = boost::filesystem;
-SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_local_posix_files]") {
+SCENARIO("copy local POSIX file to local POSIX file",
+ "[api::norns_submit_copy_local_posix_files]") {
GIVEN("a running urd instance") {
test_env env;
@@ -43,8 +43,10 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
bfs::path src_mnt, dst_mnt;
// create namespaces
- std::tie(std::ignore, src_mnt) = env.create_namespace(nsid0, "mnt/tmp0", 16384);
- std::tie(std::ignore, dst_mnt) = env.create_namespace(nsid1, "mnt/tmp1", 16384);
+ std::tie(std::ignore, src_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid1, "mnt/tmp1", 16384);
// define input names
const bfs::path src_file_at_root = "/file0";
@@ -134,33 +136,34 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
// create required output directories
env.add_to_namespace(nsid1, dst_subdir1);
- /**************************************************************************************************************/
- /* tests for error conditions */
- /**************************************************************************************************************/
+ /**********************************************************************/
+ /* tests for error conditions */
+ /**********************************************************************/
// - trying to copy a non-existing file
WHEN("copying a non-existing NORNS_LOCAL_PATH file") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_invalid_file.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_invalid_file.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "ENOENT") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -174,27 +177,28 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
// - trying to copy a non-existing directory
WHEN("copying a non-existing NORNS_LOCAL_PATH directory") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_invalid_dir.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_invalid_dir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "ENOENT") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -208,27 +212,27 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
// - trying to copy an empty directory
WHEN("copying an empty NORNS_LOCAL_PATH directory") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_empty_dir.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_empty_dir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_SUCCESS and ENOENT are reported") {
+ THEN("norns_error() reports NORNS_SUCCESS and ENOENT") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -241,33 +245,37 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
-//FIXME: DISABLED in CI until impersonation is implemented or capabilities can be added to the docker service
+//FIXME: DISABLED in CI until impersonation is implemented or
+// capabilities can be added to the docker service
#ifdef __SETCAP_TESTS__
- // - trying to copy a file from namespace root with invalid access permissions
- WHEN("copying a NORNS_LOCAL_PATH file from \"/\" without appropriate permissions to access it") {
+ // - trying to copy a file from namespace root with invalid access
+ // permissions
+ WHEN("copying a NORNS_LOCAL_PATH file from \"/\" without appropriate "
+ "permissions to access it") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_noperms_file0.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_noperms_file0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -280,30 +288,33 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- // - trying to copy a file from namespace root with invalid access permissions
- WHEN("copying a NORNS_LOCAL_PATH file from a subdir without appropriate permissions to access it") {
+ // - trying to copy a file from namespace root with invalid access
+ // permissions
+ WHEN("copying a NORNS_LOCAL_PATH file from a subdir without "
+ "appropriate permissions to access it") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_noperms_file1.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_noperms_file1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -316,30 +327,33 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- // - trying to copy a file from namespace root with invalid access permissions
- WHEN("copying a NORNS_LOCAL_PATH file from a subdir without appropriate permissions to access a parent") {
+ // - trying to copy a file from namespace root with invalid access
+ // permissions
+ WHEN("copying a NORNS_LOCAL_PATH file from a subdir without "
+ "appropriate permissions to access a parent") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_noperms_file2.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_noperms_file2.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -352,30 +366,34 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- // - trying to copy a subdir from namespace root with invalid access permissions
- WHEN("copying a NORNS_LOCAL_PATH subdir from \"/\" without appropriate permissions to access it") {
+ // - trying to copy a subdir from namespace root with invalid access
+ // permissions
+ WHEN("copying a NORNS_LOCAL_PATH subdir from \"/\" without "
+ "appropriate permissions to access it") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_noperms_subdir0.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -388,30 +406,34 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- // - trying to copy a subdir from namespace root with invalid access permissions
- WHEN("copying a NORNS_LOCAL_PATH subdir from another subdir without appropriate permissions to access it") {
+ // - trying to copy a subdir from namespace root with invalid access
+ // permissions
+ WHEN("copying a NORNS_LOCAL_PATH subdir from another subdir without "
+ "appropriate permissions to access it") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_noperms_subdir1.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -424,30 +446,34 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- // - trying to copy a subdir from namespace root with invalid access permissions
- WHEN("copying a NORNS_LOCAL_PATH subdir from another subdir without appropriate permissions to access a parent") {
+ // - trying to copy a subdir from namespace root with invalid
+ // access permissions
+ WHEN("copying a NORNS_LOCAL_PATH subdir from another subdir without "
+ "appropriate permissions to access a parent") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_noperms_subdir2.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir2.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -465,27 +491,28 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
WHEN("copying a NORNS_LOCAL_PATH through a symbolic link that leads "
"out of the src namespace") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, out_symlink.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, out_symlink.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "ENOENT") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -497,35 +524,38 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
- /**************************************************************************************************************/
- /* tests for single files */
- /**************************************************************************************************************/
+ /**********************************************************************/
+ /* tests for single files */
+ /**********************************************************************/
// cp -r ns0://file0.txt -> ns1:// = ns1://file0.txt
WHEN("copying a single NORNS_LOCAL_PATH from src namespace's root to "
- "another NORNS_LOCAL_PATH at dst namespace's root (keeping the name)") {
+ "another NORNS_LOCAL_PATH at dst namespace's root (keeping the "
+ "name)") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_file_at_root.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file_at_root.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Files are equal") {
- bfs::path src = env.get_from_namespace(nsid0, src_file_at_root);
- bfs::path dst = env.get_from_namespace(nsid1, dst_file_at_root0);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_root);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
REQUIRE(compare_files(src, dst) == true);
}
@@ -535,29 +565,32 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
// cp -r ns0://file0.txt -> ns1://file1.txt = ns1://file1.txt
WHEN("copying a single NORNS_LOCAL_PATH from src namespace's root to "
- "another NORNS_LOCAL_PATH at dst namespace's root (changing the name)") {
+ "another NORNS_LOCAL_PATH at dst namespace's root (changing the "
+ "name)") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_file_at_root.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root1.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file_at_root.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root1.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Files are equal") {
- bfs::path src = env.get_from_namespace(nsid0, src_file_at_root);
- bfs::path dst = env.get_from_namespace(nsid1, dst_file_at_root1);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_root);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root1);
REQUIRE(compare_files(src, dst) == true);
}
@@ -565,31 +598,36 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- // cp -r ns0://a/b/c/.../d/file0.txt -> ns1://file0.txt = ns1://file0.txt
- WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir to "
- "another NORNS_LOCAL_PATH at dst namespace's root (keeping the name)") {
+ // cp -r ns0://a/b/c/.../d/file0.txt ->
+ // ns1://file0.txt = ns1://file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir "
+ "to another NORNS_LOCAL_PATH at dst namespace's root "
+ "(keeping the name)") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_file_at_subdir.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Files are equal") {
- bfs::path src = env.get_from_namespace(nsid0, src_file_at_subdir);
- bfs::path dst = env.get_from_namespace(nsid1, dst_file_at_root0);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
REQUIRE(compare_files(src, dst) == true);
}
@@ -597,31 +635,36 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- // cp -r ns0://a/b/c/.../d/file0.txt -> ns1://file1.txt = ns1://file1.txt
- WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir to "
- "another NORNS_LOCAL_PATH at dst namespace's root (changing the name)") {
+ // cp -r ns0://a/b/c/.../d/file0.txt ->
+ // ns1://file1.txt = ns1://file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir "
+ "to another NORNS_LOCAL_PATH at dst namespace's root (changing "
+ "the name)") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_file_at_subdir.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root1.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root1.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Files are equal") {
- bfs::path src = env.get_from_namespace(nsid0, src_file_at_subdir);
- bfs::path dst = env.get_from_namespace(nsid1, dst_file_at_root1);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root1);
REQUIRE(compare_files(src, dst) == true);
}
@@ -629,31 +672,36 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- // cp -r ns0://file0.txt -> ns1://a/b/c/.../file0.txt = ns1://a/b/c/.../file0.txt
+ // cp -r ns0://file0.txt ->
+ // ns1://a/b/c/.../file0.txt = ns1://a/b/c/.../file0.txt
WHEN("copying a single NORNS_LOCAL_PATH from src namespace's root to "
- "another NORNS_LOCAL_PATH at a dst namespace's subdir (keeping the name)") {
+ "another NORNS_LOCAL_PATH at a dst namespace's subdir (keeping "
+ "the name)") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_file_at_root.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_subdir0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_root.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Files are equal") {
- bfs::path src = env.get_from_namespace(nsid0, src_file_at_root);
- bfs::path dst = env.get_from_namespace(nsid1, dst_file_at_subdir0);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_root);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_subdir0);
REQUIRE(compare_files(src, dst) == true);
}
@@ -661,31 +709,36 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- // cp -r ns0://file0.txt -> ns1://a/b/c/.../file1.txt = ns1://a/b/c/.../file1.txt
+ // cp -r ns0://file0.txt ->
+ // ns1://a/b/c/.../file1.txt = ns1://a/b/c/.../file1.txt
WHEN("copying a single NORNS_LOCAL_PATH from src namespace's root to "
- "another NORNS_LOCAL_PATH at a dst namespace's subdir (changing the name)") {
+ "another NORNS_LOCAL_PATH at a dst namespace's subdir (changing "
+ "the name)") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_file_at_root.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_subdir1.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_root.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir1.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Files are equal") {
- bfs::path src = env.get_from_namespace(nsid0, src_file_at_root);
- bfs::path dst = env.get_from_namespace(nsid1, dst_file_at_subdir1);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_root);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_subdir1);
REQUIRE(compare_files(src, dst) == true);
}
@@ -693,31 +746,36 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- // cp -r ns0://a/b/c/.../file0.txt -> ns1://a/b/c/.../file0.txt = ns1://a/b/c/.../file0.txt
- WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir to "
- "another NORNS_LOCAL_PATH at a dst namespace's subdir (keeping the name)") {
+ // cp -r ns0://a/b/c/.../file0.txt ->
+ // ns1://a/b/c/.../file0.txt = ns1://a/b/c/.../file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir "
+ "to another NORNS_LOCAL_PATH at a dst namespace's subdir (keeping "
+ "the name)") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_file_at_subdir.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_subdir0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Files are equal") {
- bfs::path src = env.get_from_namespace(nsid0, src_file_at_subdir);
- bfs::path dst = env.get_from_namespace(nsid1, dst_file_at_subdir0);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_subdir0);
REQUIRE(compare_files(src, dst) == true);
}
@@ -725,31 +783,36 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- // cp -r ns0://a/b/c/.../file0.txt -> ns1://a/b/c/.../file1.txt = ns1://a/b/c/.../file1.txt
- WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir to "
- "another NORNS_LOCAL_PATH at a dst namespace's subdir (changing the name)") {
+ // cp -r ns0://a/b/c/.../file0.txt ->
+ // ns1://a/b/c/.../file1.txt = ns1://a/b/c/.../file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir "
+ "to another NORNS_LOCAL_PATH at a dst namespace's subdir "
+ "(changing the name)") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_file_at_subdir.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_subdir1.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir1.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Files are equal") {
- bfs::path src = env.get_from_namespace(nsid0, src_file_at_subdir);
- bfs::path dst = env.get_from_namespace(nsid1, dst_file_at_subdir1);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_subdir1);
REQUIRE(compare_files(src, dst) == true);
}
@@ -757,31 +820,36 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- // cp -r ns0://a/b/c/.../file0.txt -> ns1://e/f/g/.../file0.txt = ns1://e/f/g/.../file0.txt
- WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir to "
- "another NORNS_LOCAL_PATH at a dst namespace's subdir (changing the parents names)") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ // cp -r ns0://a/b/c/.../file0.txt ->
+ // ns1://e/f/g/.../file0.txt = ns1://e/f/g/.../file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir "
+ "to another NORNS_LOCAL_PATH at a dst namespace's subdir "
+ "(changing the parents names)") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_file_at_subdir.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_subdir2.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir2.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Files are equal") {
- bfs::path src = env.get_from_namespace(nsid0, src_file_at_subdir);
- bfs::path dst = env.get_from_namespace(nsid1, dst_file_at_subdir2);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_subdir2);
REQUIRE(compare_files(src, dst) == true);
}
@@ -789,31 +857,36 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- // cp -r ns0://a/b/c/.../file0.txt -> ns1://e/f/g/.../file1.txt = ns1://e/f/g/.../file1.txt
- WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir to "
- "another NORNS_LOCAL_PATH at a dst namespace's subdir (changing the name)") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ // cp -r ns0://a/b/c/.../file0.txt ->
+ // ns1://e/f/g/.../file1.txt = ns1://e/f/g/.../file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir "
+ "to another NORNS_LOCAL_PATH at a dst namespace's subdir (changing "
+ "the name)") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_file_at_subdir.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_subdir3.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir3.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Files are equal") {
- bfs::path src = env.get_from_namespace(nsid0, src_file_at_subdir);
- bfs::path dst = env.get_from_namespace(nsid1, dst_file_at_subdir3);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_subdir3);
REQUIRE(compare_files(src, dst) == true);
}
@@ -821,34 +894,35 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- /**************************************************************************************************************/
- /* tests for directories */
- /**************************************************************************************************************/
+ /**********************************************************************/
+ /* tests for directories */
+ /**********************************************************************/
// cp -r /a/contents.* -> / = /contents.*
- WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from src namespace's root to "
- "dst namespace's root") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from src "
+ "namespace's root to dst namespace's root") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_subdir0.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_root.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir0.c_str()),
+ NORNS_LOCAL_PATH(nsid1, dst_root.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Copied files are identical to original") {
- bfs::path src = env.get_from_namespace(nsid0, src_subdir0);
- bfs::path dst = env.get_from_namespace(nsid1, dst_root);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_root);
REQUIRE(compare_directories(src, dst) == true);
}
@@ -860,27 +934,28 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
WHEN("copying the contents of a NORNS_LOCAL_PATH arbitrary subdir to "
"dst namespace's root") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_subdir1.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_root.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir1.c_str()),
+ NORNS_LOCAL_PATH(nsid1, dst_root.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Copied files are identical to original") {
- bfs::path src = env.get_from_namespace(nsid0, src_subdir1);
- bfs::path dst = env.get_from_namespace(nsid1, dst_root);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_root);
REQUIRE(compare_directories(src, dst) == true);
}
@@ -890,30 +965,32 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
// cp -r /a/contents.* -> /c = /c/contents.*
// (c did not exist previously)
- WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from src namespace's root to "
- "another NORNS_LOCAL_PATH subdir at dst namespace's root while changing its name") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from src "
+ "namespace's root to another NORNS_LOCAL_PATH subdir at dst "
+ "namespace's root while changing its name") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_subdir0.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_subdir0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir0.c_str()),
+ NORNS_LOCAL_PATH(nsid1, dst_subdir0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Copied files are identical to original") {
- bfs::path src = env.get_from_namespace(nsid0, src_subdir0);
- bfs::path dst = env.get_from_namespace(nsid1, dst_subdir0);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_subdir0);
REQUIRE(compare_directories(src, dst) == true);
}
@@ -923,30 +1000,32 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
// cp -r /a/contents.* -> /c = /c/contents.*
// (c did exist previously)
- WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from src namespace's root to "
- "another NORNS_LOCAL_PATH subdir at dst namespace's root while changing its name") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from src "
+ "namespace's root to another NORNS_LOCAL_PATH subdir at dst "
+ "namespace's root while changing its name") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_subdir0.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_subdir1.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir0.c_str()),
+ NORNS_LOCAL_PATH(nsid1, dst_subdir1.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Copied files are identical to original") {
- bfs::path src = env.get_from_namespace(nsid0, src_subdir0);
- bfs::path dst = env.get_from_namespace(nsid1, dst_subdir1);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_subdir1);
REQUIRE(compare_directories(src, dst) == true);
}
@@ -956,30 +1035,32 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
// cp -r /a/b/c/.../contents.* -> /c = /c/a/b/c/.../contents.*
// (c did not exist previously)
- WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from src namespace's root to "
- "another NORNS_LOCAL_PATH subdir at dst namespace's root while changing its name") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from src "
+ "namespace's root to another NORNS_LOCAL_PATH subdir at dst "
+ "namespace's root while changing its name") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_subdir1.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_subdir0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir1.c_str()),
+ NORNS_LOCAL_PATH(nsid1, dst_subdir0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Copied files are identical to original") {
- bfs::path src = env.get_from_namespace(nsid0, src_subdir1);
- bfs::path dst = env.get_from_namespace(nsid1, dst_subdir0);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_subdir0);
REQUIRE(compare_directories(src, dst) == true);
}
@@ -989,30 +1070,32 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
// cp -r /a/b/c/.../contents.* -> /c = /c/a/b/c/.../contents.*
// (c did exist previously)
- WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from src namespace's root to "
- "another NORNS_LOCAL_PATH subdir at dst namespace's root while changing its name") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from src "
+ "namespace's root to another NORNS_LOCAL_PATH subdir at dst "
+ "namespace's root while changing its name") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_subdir1.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_subdir1.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir1.c_str()),
+ NORNS_LOCAL_PATH(nsid1, dst_subdir1.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Copied files are identical to original") {
- bfs::path src = env.get_from_namespace(nsid0, src_subdir1);
- bfs::path dst = env.get_from_namespace(nsid1, dst_subdir1);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_subdir1);
REQUIRE(compare_directories(src, dst) == true);
}
@@ -1020,34 +1103,37 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- /**************************************************************************************************************/
- /* tests for soft links */
- /**************************************************************************************************************/
+ /**********************************************************************/
+ /* tests for soft links */
+ /**********************************************************************/
WHEN("copying a single NORNS_LOCAL_PATH file from src namespace's '/' "
"through a symlink also located at '/'" ) {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_symlink_at_root0.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_root0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Files are equal") {
- bfs::path src = env.get_from_namespace(nsid0, src_symlink_at_root0);
- bfs::path dst = env.get_from_namespace(nsid1, dst_file_at_root0);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_symlink_at_root0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
REQUIRE(compare_files(src, dst) == true);
}
@@ -1055,31 +1141,34 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- WHEN("copying a single NORNS_LOCAL_PATH subdir from src namespace's '/' "
- "through a symlink also located at '/'" ) {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying a single NORNS_LOCAL_PATH subdir from src namespace's "
+ "'/' through a symlink also located at '/'" ) {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_symlink_at_root1.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_root1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Directories are equal") {
- bfs::path src = env.get_from_namespace(nsid0, src_symlink_at_root1);
- bfs::path dst = env.get_from_namespace(nsid1, dst_file_at_root0);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_symlink_at_root1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
REQUIRE(compare_directories(src, dst) == true);
}
@@ -1090,28 +1179,31 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
WHEN("copying a single NORNS_LOCAL_PATH arbitrary subdir"
"through a symlink also located at '/'" ) {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_symlink_at_root2.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_root2.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Directories are equal") {
- bfs::path src = env.get_from_namespace(nsid0, src_symlink_at_root2);
- bfs::path dst = env.get_from_namespace(nsid1, dst_file_at_root0);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_symlink_at_root2);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
REQUIRE(compare_directories(src, dst) == true);
}
@@ -1122,28 +1214,32 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
WHEN("copying a single NORNS_LOCAL_PATH file from src namespace's '/' "
"through a symlink located in a subdir" ) {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_symlink_at_subdir0.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_subdir0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Files are equal") {
- bfs::path src = env.get_from_namespace(nsid0, src_symlink_at_subdir0);
- bfs::path dst = env.get_from_namespace(nsid1, dst_file_at_root0);
+ bfs::path src =
+ env.get_from_namespace(nsid0,
+ src_symlink_at_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
REQUIRE(compare_files(src, dst) == true);
}
@@ -1151,31 +1247,34 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
}
- WHEN("copying a single NORNS_LOCAL_PATH subdir from src namespace's '/' "
- "through a symlink also located at subdir" ) {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying a single NORNS_LOCAL_PATH subdir from src namespace's "
+ "'/' through a symlink also located at subdir" ) {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_symlink_at_subdir1.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_subdir1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Directories are equal") {
- bfs::path src = env.get_from_namespace(nsid0, src_symlink_at_subdir1);
- bfs::path dst = env.get_from_namespace(nsid1, dst_file_at_root0);
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_symlink_at_subdir1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
REQUIRE(compare_directories(src, dst) == true);
}
@@ -1186,28 +1285,32 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
WHEN("copying a single NORNS_LOCAL_PATH arbitrary subdir"
"through a symlink also located at a subdir" ) {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_symlink_at_subdir2.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_subdir2.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Directories are equal") {
- bfs::path src = env.get_from_namespace(nsid0, src_symlink_at_subdir2);
- bfs::path dst = env.get_from_namespace(nsid1, dst_file_at_root0);
+ bfs::path src =
+ env.get_from_namespace(nsid0,
+ src_symlink_at_subdir2);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
REQUIRE(compare_directories(src, dst) == true);
}
@@ -1238,7 +1341,8 @@ SCENARIO("copy local POSIX file to local POSIX file", "[api::norns_submit_copy_l
}
-SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_copy_buffer_to_file]") {
+SCENARIO("copy local memory buffer to local POSIX file",
+ "[api::norns_submit_copy_buffer_to_file]") {
GIVEN("a running urd instance") {
test_env env;
@@ -1247,7 +1351,8 @@ SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_cop
bfs::path dst_mnt;
// create namespaces
- std::tie(std::ignore, dst_mnt) = env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
// create input data buffer
std::vector input_data(100, 42);
@@ -1273,16 +1378,19 @@ SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_cop
/* tests for error conditions */
/**************************************************************************************************************/
//TODO
- // - copy a valid but removed memory region (cannot control => undefined behavior)
- // - providing a non-existing directory path (i.e. finished with /) as output name
- // - providing an existing path that points to a directory as output name
+ // - copy a valid but removed memory region
+ // (cannot control => undefined behavior)
+ // - providing a non-existing directory path (i.e. finished with /) as
+ // output name
+ // - providing an existing path that points to a directory as
+ // output name
WHEN("copying an invalid memory region to a local POSIX file") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_MEMORY_REGION((void*) 0x42, region_size),
- NORNS_LOCAL_PATH(nsid0, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION((void*) 0x42, region_size),
+ NORNS_LOCAL_PATH(nsid0,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
@@ -1296,9 +1404,10 @@ SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_cop
THEN("norns_wait() return NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_ESYSTEMERROR and EFAULT") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "EFAULT") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -1309,13 +1418,14 @@ SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_cop
}
}
- WHEN("copying a valid memory region to a local POSIX file located at '/'") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying a valid memory region to a local POSIX file located "
+ "at '/'") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_MEMORY_REGION(region_addr, region_size),
- NORNS_LOCAL_PATH(nsid0, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
@@ -1331,7 +1441,8 @@ SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_cop
THEN("Output file contains buffer data") {
- bfs::path dst = env.get_from_namespace(nsid0, dst_file_at_root0);
+ bfs::path dst =
+ env.get_from_namespace(nsid0, dst_file_at_root0);
REQUIRE(compare(input_data, dst) == true);
}
@@ -1339,13 +1450,14 @@ SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_cop
}
}
- WHEN("copying a valid memory region to a local POSIX file located at a subdir") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying a valid memory region to a local POSIX file located at a "
+ "subdir") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_MEMORY_REGION(region_addr, region_size),
- NORNS_LOCAL_PATH(nsid0, dst_file_at_subdir0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0,
+ dst_file_at_subdir0.c_str()));
norns_error_t rv = norns_submit(&task);
@@ -1361,7 +1473,8 @@ SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_cop
THEN("Output file contains buffer data") {
- bfs::path dst = env.get_from_namespace(nsid0, dst_file_at_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid0, dst_file_at_subdir0);
REQUIRE(compare(input_data, dst) == true);
}
@@ -1371,11 +1484,10 @@ SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_cop
WHEN("copying a valid memory region to a local POSIX /") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_MEMORY_REGION(region_addr, region_size),
- NORNS_LOCAL_PATH(nsid0, dst_root.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0, dst_root.c_str()));
norns_error_t rv = norns_submit(&task);
@@ -1384,13 +1496,13 @@ SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_cop
}
}
- WHEN("copying a valid memory region to a local POSIX existing directory at /") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying a valid memory region to a local POSIX existing "
+ "directory at /") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_MEMORY_REGION(region_addr, region_size),
- NORNS_LOCAL_PATH(nsid0, dst_subdir0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0, dst_subdir0.c_str()));
norns_error_t rv = norns_submit(&task);
@@ -1399,13 +1511,13 @@ SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_cop
}
}
- WHEN("copying a valid memory region to a local POSIX existing directory at /") {
+ WHEN("copying a valid memory region to a local POSIX existing "
+ "directory at /") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_MEMORY_REGION(region_addr, region_size),
- NORNS_LOCAL_PATH(nsid0, dst_subdir1.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0, dst_subdir1.c_str()));
norns_error_t rv = norns_submit(&task);
@@ -1419,9 +1531,10 @@ SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_cop
THEN("norns_wait() return NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_ESYSTEMERROR and EISDIR") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "EISDIR") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
@@ -1431,13 +1544,13 @@ SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_cop
}
}
- WHEN("copying a valid memory region to a local POSIX existing directory at an arbitary subdir") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying a valid memory region to a local POSIX existing "
+ "directory at an arbitary subdir") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_MEMORY_REGION(region_addr, region_size),
- NORNS_LOCAL_PATH(nsid0, dst_subdir2.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0, dst_subdir2.c_str()));
norns_error_t rv = norns_submit(&task);
@@ -1446,13 +1559,13 @@ SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_cop
}
}
- WHEN("copying a valid memory region to a local POSIX existing directory at an arbitary subdir") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying a valid memory region to a local POSIX existing "
+ "directory at an arbitary subdir") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_MEMORY_REGION(region_addr, region_size),
- NORNS_LOCAL_PATH(nsid0, dst_subdir3.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0, dst_subdir3.c_str()));
norns_error_t rv = norns_submit(&task);
@@ -1466,9 +1579,10 @@ SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_cop
THEN("norns_wait() return NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_ESYSTEMERROR and EISDIR") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "EISDIR") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
@@ -1480,13 +1594,13 @@ SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_cop
// i.e. a destination path that 'looks like' a directory
- WHEN("copying a valid memory region to a local POSIX non-existing directory") {
+ WHEN("copying a valid memory region to a local POSIX non-existing "
+ "directory") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_MEMORY_REGION(region_addr, region_size),
- NORNS_LOCAL_PATH(nsid0, dst_subdir4.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0, dst_subdir4.c_str()));
norns_error_t rv = norns_submit(&task);
@@ -1495,13 +1609,13 @@ SCENARIO("copy local memory buffer to local POSIX file", "[api::norns_submit_cop
}
}
- WHEN("copying a valid memory region to a local POSIX non-existing directory") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying a valid memory region to a local POSIX non-existing "
+ "directory") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_MEMORY_REGION(region_addr, region_size),
- NORNS_LOCAL_PATH(nsid0, dst_subdir5.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0, dst_subdir5.c_str()));
norns_error_t rv = norns_submit(&task);
diff --git a/tests/api-copy-remote-data.cpp b/tests/api-copy-remote-data.cpp
index 5447d1c5d62cee43c8b9c1950ba99924809d7bda..6a88aec28c2a16a3a7381f44108efc01900ac60d 100644
--- a/tests/api-copy-remote-data.cpp
+++ b/tests/api-copy-remote-data.cpp
@@ -26,7 +26,6 @@
*************************************************************************/
#include "norns.h"
-#include "nornsctl.h"
#include "test-env.hpp"
#include "compare-files.hpp"
#include "catch.hpp"
@@ -170,7 +169,7 @@ SCENARIO("errors copying local POSIX path to remote POSIX path",
THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -205,7 +204,7 @@ SCENARIO("errors copying local POSIX path to remote POSIX path",
THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -240,7 +239,7 @@ SCENARIO("errors copying local POSIX path to remote POSIX path",
THEN("NORNS_SUCCESS and ENOENT are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -282,7 +281,7 @@ SCENARIO("errors copying local POSIX path to remote POSIX path",
THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL "
"are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -320,7 +319,7 @@ SCENARIO("errors copying local POSIX path to remote POSIX path",
THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -359,7 +358,7 @@ SCENARIO("errors copying local POSIX path to remote POSIX path",
THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL "
"are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -399,7 +398,7 @@ SCENARIO("errors copying local POSIX path to remote POSIX path",
THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL "
"are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -438,7 +437,7 @@ SCENARIO("errors copying local POSIX path to remote POSIX path",
THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -478,7 +477,7 @@ SCENARIO("errors copying local POSIX path to remote POSIX path",
THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL "
"are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -517,7 +516,7 @@ SCENARIO("errors copying local POSIX path to remote POSIX path",
THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -672,9 +671,9 @@ SCENARIO("copy local POSIX file to remote POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -720,9 +719,9 @@ SCENARIO("copy local POSIX file to remote POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -767,9 +766,9 @@ SCENARIO("copy local POSIX file to remote POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -816,9 +815,9 @@ SCENARIO("copy local POSIX file to remote POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -863,9 +862,9 @@ SCENARIO("copy local POSIX file to remote POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -910,9 +909,9 @@ SCENARIO("copy local POSIX file to remote POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -957,9 +956,9 @@ SCENARIO("copy local POSIX file to remote POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -1004,9 +1003,9 @@ SCENARIO("copy local POSIX file to remote POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -1051,9 +1050,9 @@ SCENARIO("copy local POSIX file to remote POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -1098,9 +1097,9 @@ SCENARIO("copy local POSIX file to remote POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -1262,9 +1261,9 @@ SCENARIO("copy local POSIX file to remote POSIX subdir",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -1306,9 +1305,9 @@ SCENARIO("copy local POSIX file to remote POSIX subdir",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -1352,9 +1351,9 @@ SCENARIO("copy local POSIX file to remote POSIX subdir",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -1398,9 +1397,9 @@ SCENARIO("copy local POSIX file to remote POSIX subdir",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -1444,9 +1443,9 @@ SCENARIO("copy local POSIX file to remote POSIX subdir",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -1490,9 +1489,9 @@ SCENARIO("copy local POSIX file to remote POSIX subdir",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -1577,9 +1576,9 @@ SCENARIO("copy local memory region to remote POSIX file",
THEN("norns_wait() return NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -1616,9 +1615,9 @@ SCENARIO("copy local memory region to remote POSIX file",
// wait until the task completes
rv = norns_wait(&task);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -1727,10 +1726,10 @@ SCENARIO("errors copying local memory region to remote POSIX file",
THEN("norns_wait() return NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_ESYSTEMERROR and "
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
"EFAULT") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -1812,10 +1811,10 @@ SCENARIO("errors copying local memory region to remote POSIX file",
THEN("norns_wait() return NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_ESYSTEMERROR and "
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
"EISDIR") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
@@ -1875,10 +1874,10 @@ SCENARIO("errors copying local memory region to remote POSIX file",
THEN("norns_wait() return NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_ESYSTEMERROR and "
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
"EISDIR") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
@@ -2094,9 +2093,9 @@ SCENARIO("copy local POSIX path to remote POSIX path involving links",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -2138,9 +2137,9 @@ SCENARIO("copy local POSIX path to remote POSIX path involving links",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -2182,9 +2181,9 @@ SCENARIO("copy local POSIX path to remote POSIX path involving links",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -2226,9 +2225,9 @@ SCENARIO("copy local POSIX path to remote POSIX path involving links",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -2271,9 +2270,9 @@ SCENARIO("copy local POSIX path to remote POSIX path involving links",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -2316,9 +2315,9 @@ SCENARIO("copy local POSIX path to remote POSIX path involving links",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -2480,7 +2479,7 @@ SCENARIO("errors copying remote POSIX path to local POSIX path",
THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -2516,7 +2515,7 @@ SCENARIO("errors copying remote POSIX path to local POSIX path",
THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -2552,7 +2551,7 @@ SCENARIO("errors copying remote POSIX path to local POSIX path",
THEN("NORNS_SUCCESS and ENOENT are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -2595,7 +2594,7 @@ SCENARIO("errors copying remote POSIX path to local POSIX path",
THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL "
"are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -2635,7 +2634,7 @@ SCENARIO("errors copying remote POSIX path to local POSIX path",
THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -2674,7 +2673,7 @@ SCENARIO("errors copying remote POSIX path to local POSIX path",
THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL "
"are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -2714,7 +2713,7 @@ SCENARIO("errors copying remote POSIX path to local POSIX path",
THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL "
"are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -2753,7 +2752,7 @@ SCENARIO("errors copying remote POSIX path to local POSIX path",
THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -2793,7 +2792,7 @@ SCENARIO("errors copying remote POSIX path to local POSIX path",
THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL "
"are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -2832,7 +2831,7 @@ SCENARIO("errors copying remote POSIX path to local POSIX path",
THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -2988,9 +2987,9 @@ SCENARIO("copy remote POSIX file to local POSIX file",
THEN("norns_wait() return NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -3035,9 +3034,9 @@ SCENARIO("copy remote POSIX file to local POSIX file",
THEN("norns_wait() return NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -3081,9 +3080,9 @@ SCENARIO("copy remote POSIX file to local POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -3129,9 +3128,9 @@ SCENARIO("copy remote POSIX file to local POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -3177,9 +3176,9 @@ SCENARIO("copy remote POSIX file to local POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -3225,9 +3224,9 @@ SCENARIO("copy remote POSIX file to local POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -3273,9 +3272,9 @@ SCENARIO("copy remote POSIX file to local POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -3321,9 +3320,9 @@ SCENARIO("copy remote POSIX file to local POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -3369,9 +3368,9 @@ SCENARIO("copy remote POSIX file to local POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -3417,9 +3416,9 @@ SCENARIO("copy remote POSIX file to local POSIX file",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -3579,9 +3578,9 @@ SCENARIO("copy remote POSIX subdir to local POSIX subdir",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -3624,9 +3623,9 @@ SCENARIO("copy remote POSIX subdir to local POSIX subdir",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -3671,9 +3670,9 @@ SCENARIO("copy remote POSIX subdir to local POSIX subdir",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -3718,9 +3717,9 @@ SCENARIO("copy remote POSIX subdir to local POSIX subdir",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -3765,9 +3764,9 @@ SCENARIO("copy remote POSIX subdir to local POSIX subdir",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -3812,9 +3811,9 @@ SCENARIO("copy remote POSIX subdir to local POSIX subdir",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -3991,9 +3990,9 @@ SCENARIO("copy remote POSIX path to local POSIX path involving links",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -4035,9 +4034,9 @@ SCENARIO("copy remote POSIX path to local POSIX path involving links",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -4079,9 +4078,9 @@ SCENARIO("copy remote POSIX path to local POSIX path involving links",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -4123,9 +4122,9 @@ SCENARIO("copy remote POSIX path to local POSIX path involving links",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -4168,9 +4167,9 @@ SCENARIO("copy remote POSIX path to local POSIX path involving links",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
@@ -4213,9 +4212,9 @@ SCENARIO("copy remote POSIX path to local POSIX path involving links",
THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("norns_status() reports NORNS_EFINISHED") {
+ THEN("norns_error() reports NORNS_EFINISHED") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHED);
diff --git a/tests/api-ctl-copy-local-data.cpp b/tests/api-ctl-copy-local-data.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0b8318a387f2050bb9c29b8dd0735e5af8a4acd3
--- /dev/null
+++ b/tests/api-ctl-copy-local-data.cpp
@@ -0,0 +1,1638 @@
+/*************************************************************************
+ * Copyright (C) 2017-2018 Barcelona Supercomputing Center *
+ * Centro Nacional de Supercomputacion *
+ * All rights reserved. *
+ * *
+ * This file is part of the NORNS Data Scheduler, a service that allows *
+ * other programs to start, track and manage asynchronous transfers of *
+ * data resources transfers requests between different storage backends. *
+ * *
+ * See AUTHORS file in the top level directory for information *
+ * regarding developers and contributors. *
+ * *
+ * The NORNS 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 NORNS 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 the NORNS Data Scheduler. If not, see *
+ * . *
+ *************************************************************************/
+
+#include "nornsctl.h"
+#include "test-env.hpp"
+#include "compare-files.hpp"
+#include "catch.hpp"
+
+namespace bfs = boost::filesystem;
+
+SCENARIO("copy local POSIX file to local POSIX file (admin)",
+ "[api::nornsctl_submit_copy_local_posix_files]") {
+ GIVEN("a running urd instance") {
+
+ test_env env;
+
+ const char* nsid0 = "tmp0";
+ const char* nsid1 = "tmp1";
+ bfs::path src_mnt, dst_mnt;
+
+ // create namespaces
+ std::tie(std::ignore, src_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid1, "mnt/tmp1", 16384);
+
+ // define input names
+ const bfs::path src_file_at_root = "/file0";
+ const bfs::path src_file_at_subdir = "/a/b/c/d/file0";
+ const bfs::path src_invalid_file = "/a/b/c/d/does_not_exist_file0";
+ const bfs::path src_invalid_dir = "/a/b/c/d/does_not_exist_dir0";
+ const bfs::path src_subdir0 = "/input_dir0";
+ const bfs::path src_subdir1 = "/input_dir0/a/b/c/input_dir1";
+ const bfs::path src_empty_dir = "/empty_dir0";
+
+ const bfs::path src_noperms_file0 = "/noperms_file0";
+ const bfs::path src_noperms_file1 = "/noperms/a/b/c/d/noperms_file0"; // parents accessible
+ const bfs::path src_noperms_file2 = "/noperms/noperms_subdir0/file0"; // parents non-accessible
+ const bfs::path src_noperms_subdir0 = "/noperms_subdir0"; // subdir non-accessible
+ const bfs::path src_noperms_subdir1 = "/noperms/a/b/c/d/noperms_subdir1"; // child subdir non-accessible
+ const bfs::path src_noperms_subdir2 = "/noperms/noperms_subdir2/a"; // parent subdir non-accessible
+
+ const bfs::path src_symlink_at_root0 = "/symlink0";
+ const bfs::path src_symlink_at_root1 = "/symlink1";
+ const bfs::path src_symlink_at_root2 = "/symlink2";
+ const bfs::path src_symlink_at_subdir0 = "/foo/bar/baz/symlink0";
+ const bfs::path src_symlink_at_subdir1 = "/foo/bar/baz/symlink1";
+ const bfs::path src_symlink_at_subdir2 = "/foo/bar/baz/symlink2";
+
+ const bfs::path dst_root = "/";
+ const bfs::path dst_subdir0 = "/output_dir0";
+ const bfs::path dst_subdir1 = "/output_dir1";
+ const bfs::path dst_file_at_root0 = "/file0"; // same basename
+ const bfs::path dst_file_at_root1 = "/file1"; // different basename
+ const bfs::path dst_file_at_subdir0 = "/a/b/c/d/file0"; // same fullname
+ const bfs::path dst_file_at_subdir1 = "/a/b/c/d/file1"; // same parents, different basename
+ const bfs::path dst_file_at_subdir2 = "/e/f/g/h/i/file0"; // different parents, same basename
+ const bfs::path dst_file_at_subdir3 = "/e/f/g/h/i/file1"; // different fullname
+
+ // create input data
+ env.add_to_namespace(nsid0, src_file_at_root, 4096);
+ env.add_to_namespace(nsid0, src_file_at_subdir, 8192);
+ env.add_to_namespace(nsid0, src_subdir0);
+ env.add_to_namespace(nsid0, src_subdir1);
+ env.add_to_namespace(nsid0, src_empty_dir);
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir0 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir1 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ // create input data with special permissions
+ auto p = env.add_to_namespace(nsid0, src_noperms_file0, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file1, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file2, 0);
+ env.remove_access(p.parent_path());
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir1);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir2);
+ env.remove_access(p.parent_path());
+
+ // add symlinks to the namespace
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_root0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_root1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_root2);
+
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_subdir0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_subdir1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_subdir2);
+
+ // manually create a symlink leading outside namespace 0
+ boost::system::error_code ec;
+ const bfs::path out_symlink = "/out_symlink";
+ bfs::create_symlink(dst_mnt, src_mnt / out_symlink, ec);
+ REQUIRE(!ec);
+
+
+ // create required output directories
+ env.add_to_namespace(nsid1, dst_subdir1);
+
+ /**********************************************************************/
+ /* tests for error conditions */
+ /**********************************************************************/
+ // - trying to copy a non-existing file
+ WHEN("copying a non-existing NORNS_LOCAL_PATH file") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_invalid_file.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "ENOENT") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == ENOENT);
+ }
+ }
+ }
+ }
+
+ // - trying to copy a non-existing directory
+ WHEN("copying a non-existing NORNS_LOCAL_PATH directory") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_invalid_dir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "ENOENT") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == ENOENT);
+ }
+ }
+ }
+ }
+
+ // - trying to copy an empty directory
+ WHEN("copying an empty NORNS_LOCAL_PATH directory") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_empty_dir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_SUCCESS and ENOENT") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+ REQUIRE(stats.st_task_error == NORNS_SUCCESS);
+ REQUIRE(stats.st_sys_errno == 0);
+
+ REQUIRE(bfs::exists(dst_mnt / dst_file_at_root0));
+ }
+ }
+ }
+ }
+
+//FIXME: DISABLED in CI until impersonation is implemented or
+// capabilities can be added to the docker service
+#ifdef __SETCAP_TESTS__
+
+ // - trying to copy a file from namespace root with invalid access
+ // permissions
+ WHEN("copying a NORNS_LOCAL_PATH file from \"/\" without appropriate "
+ "permissions to access it") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_file0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a file from namespace root with invalid access
+ // permissions
+ WHEN("copying a NORNS_LOCAL_PATH file from a subdir without "
+ "appropriate permissions to access it") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_file1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a file from namespace root with invalid access
+ // permissions
+ WHEN("copying a NORNS_LOCAL_PATH file from a subdir without "
+ "appropriate permissions to access a parent") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_file2.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a subdir from namespace root with invalid access
+ // permissions
+ WHEN("copying a NORNS_LOCAL_PATH subdir from \"/\" without "
+ "appropriate permissions to access it") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a subdir from namespace root with invalid access
+ // permissions
+ WHEN("copying a NORNS_LOCAL_PATH subdir from another subdir without "
+ "appropriate permissions to access it") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a subdir from namespace root with invalid
+ // access permissions
+ WHEN("copying a NORNS_LOCAL_PATH subdir from another subdir without "
+ "appropriate permissions to access a parent") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir2.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+#endif
+
+ // symlink leading out of namespace
+ WHEN("copying a NORNS_LOCAL_PATH through a symbolic link that leads "
+ "out of the src namespace") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, out_symlink.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "ENOENT") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == ENOENT);
+ }
+ }
+ }
+ }
+
+
+ /**********************************************************************/
+ /* tests for single files */
+ /**********************************************************************/
+ // cp -r ns0://file0.txt -> ns1:// = ns1://file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from src namespace's root to "
+ "another NORNS_LOCAL_PATH at dst namespace's root (keeping the "
+ "name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_root.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Files are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_root);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://file0.txt -> ns1://file1.txt = ns1://file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from src namespace's root to "
+ "another NORNS_LOCAL_PATH at dst namespace's root (changing the "
+ "name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_root.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_root);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root1);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../d/file0.txt ->
+ // ns1://file0.txt = ns1://file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir "
+ "to another NORNS_LOCAL_PATH at dst namespace's root "
+ "(keeping the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../d/file0.txt ->
+ // ns1://file1.txt = ns1://file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir "
+ "to another NORNS_LOCAL_PATH at dst namespace's root (changing "
+ "the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root1);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://file0.txt ->
+ // ns1://a/b/c/.../file0.txt = ns1://a/b/c/.../file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from src namespace's root to "
+ "another NORNS_LOCAL_PATH at a dst namespace's subdir (keeping "
+ "the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_root.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_root);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_subdir0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://file0.txt ->
+ // ns1://a/b/c/.../file1.txt = ns1://a/b/c/.../file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from src namespace's root to "
+ "another NORNS_LOCAL_PATH at a dst namespace's subdir (changing "
+ "the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_root.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_root);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_subdir1);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../file0.txt ->
+ // ns1://a/b/c/.../file0.txt = ns1://a/b/c/.../file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir "
+ "to another NORNS_LOCAL_PATH at a dst namespace's subdir (keeping "
+ "the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_subdir0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../file0.txt ->
+ // ns1://a/b/c/.../file1.txt = ns1://a/b/c/.../file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir "
+ "to another NORNS_LOCAL_PATH at a dst namespace's subdir "
+ "(changing the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_subdir1);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../file0.txt ->
+ // ns1://e/f/g/.../file0.txt = ns1://e/f/g/.../file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir "
+ "to another NORNS_LOCAL_PATH at a dst namespace's subdir "
+ "(changing the parents names)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir2.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_subdir2);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../file0.txt ->
+ // ns1://e/f/g/.../file1.txt = ns1://e/f/g/.../file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a src namespace's subdir "
+ "to another NORNS_LOCAL_PATH at a dst namespace's subdir (changing "
+ "the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir3.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_subdir3);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ /**********************************************************************/
+ /* tests for directories */
+ /**********************************************************************/
+ // cp -r /a/contents.* -> / = /contents.*
+ WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from src "
+ "namespace's root to dst namespace's root") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir0.c_str()),
+ NORNS_LOCAL_PATH(nsid1, dst_root.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Copied files are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_root);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ // cp -r /a/b/c/.../contents.* -> / = /contents.*
+ WHEN("copying the contents of a NORNS_LOCAL_PATH arbitrary subdir to "
+ "dst namespace's root") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir1.c_str()),
+ NORNS_LOCAL_PATH(nsid1, dst_root.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Copied files are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_root);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ // cp -r /a/contents.* -> /c = /c/contents.*
+ // (c did not exist previously)
+ WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from src "
+ "namespace's root to another NORNS_LOCAL_PATH subdir at dst "
+ "namespace's root while changing its name") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir0.c_str()),
+ NORNS_LOCAL_PATH(nsid1, dst_subdir0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Copied files are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_subdir0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ // cp -r /a/contents.* -> /c = /c/contents.*
+ // (c did exist previously)
+ WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from src "
+ "namespace's root to another NORNS_LOCAL_PATH subdir at dst "
+ "namespace's root while changing its name") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir0.c_str()),
+ NORNS_LOCAL_PATH(nsid1, dst_subdir1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Copied files are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_subdir1);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ // cp -r /a/b/c/.../contents.* -> /c = /c/a/b/c/.../contents.*
+ // (c did not exist previously)
+ WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from src "
+ "namespace's root to another NORNS_LOCAL_PATH subdir at dst "
+ "namespace's root while changing its name") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir1.c_str()),
+ NORNS_LOCAL_PATH(nsid1, dst_subdir0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Copied files are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_subdir0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ // cp -r /a/b/c/.../contents.* -> /c = /c/a/b/c/.../contents.*
+ // (c did exist previously)
+ WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from src "
+ "namespace's root to another NORNS_LOCAL_PATH subdir at dst "
+ "namespace's root while changing its name") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir1.c_str()),
+ NORNS_LOCAL_PATH(nsid1, dst_subdir1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Copied files are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_subdir1);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ /**********************************************************************/
+ /* tests for soft links */
+ /**********************************************************************/
+ WHEN("copying a single NORNS_LOCAL_PATH file from src namespace's '/' "
+ "through a symlink also located at '/'" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_root0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Files are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_symlink_at_root0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ WHEN("copying a single NORNS_LOCAL_PATH subdir from src namespace's "
+ "'/' through a symlink also located at '/'" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_root1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Directories are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_symlink_at_root1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ WHEN("copying a single NORNS_LOCAL_PATH arbitrary subdir"
+ "through a symlink also located at '/'" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_root2.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Directories are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_symlink_at_root2);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ WHEN("copying a single NORNS_LOCAL_PATH file from src namespace's '/' "
+ "through a symlink located in a subdir" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_subdir0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Files are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0,
+ src_symlink_at_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ WHEN("copying a single NORNS_LOCAL_PATH subdir from src namespace's "
+ "'/' through a symlink also located at subdir" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_subdir1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Directories are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_symlink_at_subdir1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ WHEN("copying a single NORNS_LOCAL_PATH arbitrary subdir"
+ "through a symlink also located at a subdir" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_subdir2.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Directories are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0,
+ src_symlink_at_subdir2);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+
+ env.notify_success();
+ }
+
+#ifndef USE_REAL_DAEMON
+ GIVEN("a non-running urd instance") {
+ WHEN("attempting to request a transfer") {
+
+ norns_iotask_t task = NORNSCTL_IOTASK(
+ NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH("nvml0://", "/a/b/c/"),
+ NORNS_REMOTE_PATH("nvml0://", "node1", "/a/b/d/"));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ECONNFAILED is returned") {
+ REQUIRE(rv == NORNS_ECONNFAILED);
+ }
+ }
+ }
+#endif
+}
+
+
+SCENARIO("copy local memory buffer to local POSIX file (admin)",
+ "[api::nornsctl_submit_copy_buffer_to_file]") {
+ GIVEN("a running urd instance") {
+
+ test_env env;
+
+ const char* nsid0 = "tmp0";
+ bfs::path dst_mnt;
+
+ // create namespaces
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+
+ // create input data buffer
+ std::vector input_data(100, 42);
+ void* region_addr = input_data.data();
+ size_t region_size = input_data.size() * sizeof(int);
+
+ // output names
+ const bfs::path dst_file_at_root0 = "/file0";
+ const bfs::path dst_file_at_subdir0 = "/a/b/c/d/file0";
+ const bfs::path dst_root = "/";
+ const bfs::path dst_subdir0 = "/output_dir0/"; // existing
+ const bfs::path dst_subdir1 = "/output_dir0"; // existing but does not look as a directory
+ const bfs::path dst_subdir2 = "/output_dir0/a/b/c/d/"; // existing
+ const bfs::path dst_subdir3 = "/output_dir0/a/b/c/d"; // existing but does not look as a directory
+ const bfs::path dst_subdir4 = "/output_dir1/"; // non-existing
+ const bfs::path dst_subdir5 = "/output_dir1/a/b/c/d/"; // non-existing
+
+ // create required output directories
+ env.add_to_namespace(nsid0, dst_subdir0);
+ env.add_to_namespace(nsid0, dst_subdir2);
+
+ /**************************************************************************************************************/
+ /* tests for error conditions */
+ /**************************************************************************************************************/
+ //TODO
+ // - copy a valid but removed memory region
+ // (cannot control => undefined behavior)
+ // - providing a non-existing directory path (i.e. finished with /) as
+ // output name
+ // - providing an existing path that points to a directory as
+ // output name
+ WHEN("copying an invalid memory region to a local POSIX file") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION((void*) 0x42, region_size),
+ NORNS_LOCAL_PATH(nsid0,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() return NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EFAULT") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == EFAULT);
+ }
+ }
+ }
+ }
+
+ WHEN("copying a valid memory region to a local POSIX file located "
+ "at '/'") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() return NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Output file contains buffer data") {
+
+ bfs::path dst =
+ env.get_from_namespace(nsid0, dst_file_at_root0);
+
+ REQUIRE(compare(input_data, dst) == true);
+ }
+ }
+ }
+ }
+
+ WHEN("copying a valid memory region to a local POSIX file located at a "
+ "subdir") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0,
+ dst_file_at_subdir0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() return NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Output file contains buffer data") {
+
+ bfs::path dst =
+ env.get_from_namespace(nsid0, dst_file_at_subdir0);
+
+ REQUIRE(compare(input_data, dst) == true);
+ }
+ }
+ }
+ }
+
+ WHEN("copying a valid memory region to a local POSIX /") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0, dst_root.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_EBADARGS") {
+ REQUIRE(rv == NORNS_EBADARGS);
+ }
+ }
+
+ WHEN("copying a valid memory region to a local POSIX existing "
+ "directory at /") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0, dst_subdir0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_EBADARGS") {
+ REQUIRE(rv == NORNS_EBADARGS);
+ }
+ }
+
+ WHEN("copying a valid memory region to a local POSIX existing "
+ "directory at /") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0, dst_subdir1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() return NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EISDIR") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == EISDIR);
+ }
+ }
+ }
+ }
+
+ WHEN("copying a valid memory region to a local POSIX existing "
+ "directory at an arbitary subdir") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0, dst_subdir2.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_EBADARGS") {
+ REQUIRE(rv == NORNS_EBADARGS);
+ }
+ }
+
+ WHEN("copying a valid memory region to a local POSIX existing "
+ "directory at an arbitary subdir") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0, dst_subdir3.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() return NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EISDIR") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == EISDIR);
+ }
+ }
+ }
+ }
+
+
+ // i.e. a destination path that 'looks like' a directory
+ WHEN("copying a valid memory region to a local POSIX non-existing "
+ "directory") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0, dst_subdir4.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_EBADARGS") {
+ REQUIRE(rv == NORNS_EBADARGS);
+ }
+ }
+
+ WHEN("copying a valid memory region to a local POSIX non-existing "
+ "directory") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_LOCAL_PATH(nsid0, dst_subdir5.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_EBADARGS") {
+ REQUIRE(rv == NORNS_EBADARGS);
+ }
+ }
+
+ env.notify_success();
+ }
+}
diff --git a/tests/api-ctl-copy-remote-data.cpp b/tests/api-ctl-copy-remote-data.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..82c23160aa2f47d17ea7acc6e2a01f94505e1e72
--- /dev/null
+++ b/tests/api-ctl-copy-remote-data.cpp
@@ -0,0 +1,4239 @@
+/*************************************************************************
+ * Copyright (C) 2017-2018 Barcelona Supercomputing Center *
+ * Centro Nacional de Supercomputacion *
+ * All rights reserved. *
+ * *
+ * This file is part of the NORNS Data Scheduler, a service that allows *
+ * other programs to start, track and manage asynchronous transfers of *
+ * data resources transfers requests between different storage backends. *
+ * *
+ * See AUTHORS file in the top level directory for information *
+ * regarding developers and contributors. *
+ * *
+ * The NORNS 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 NORNS 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 the NORNS Data Scheduler. If not, see *
+ * . *
+ *************************************************************************/
+
+#include "nornsctl.h"
+#include "test-env.hpp"
+#include "compare-files.hpp"
+#include "catch.hpp"
+
+namespace bfs = boost::filesystem;
+
+/******************************************************************************/
+/* tests for push transfers (errors) */
+/******************************************************************************/
+SCENARIO("errors copying local POSIX path to remote POSIX path (admin)",
+ "[api::nornsctl_submit_push_errors]") {
+ GIVEN("a running urd instance") {
+
+ /**********************************************************************/
+ /* setup common environment */
+ /**********************************************************************/
+ test_env env(false);
+
+ const char* nsid0 = "tmp0";
+ const char* nsid1 = "tmp1";
+ const char* remote_host = "127.0.0.1:42000";
+ bfs::path src_mnt, dst_mnt;
+
+ // create namespaces
+ std::tie(std::ignore, src_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid1, "mnt/tmp1", 16384);
+
+ // define input names
+ const bfs::path src_file_at_root = "/file0";
+ const bfs::path src_file_at_subdir = "/a/b/c/d/file0";
+ const bfs::path src_invalid_file = "/a/b/c/d/does_not_exist_file0";
+ const bfs::path src_invalid_dir = "/a/b/c/d/does_not_exist_dir0";
+ const bfs::path src_subdir0 = "/input_dir0";
+ const bfs::path src_subdir1 = "/input_dir0/a/b/c/input_dir1";
+ const bfs::path src_empty_dir = "/empty_dir0";
+
+ const bfs::path src_noperms_file0 = "/noperms_file0";
+ const bfs::path src_noperms_file1 = "/noperms/a/b/c/d/noperms_file0"; // parents accessible
+ const bfs::path src_noperms_file2 = "/noperms/noperms_subdir0/file0"; // parents non-accessible
+ const bfs::path src_noperms_subdir0 = "/noperms_subdir0"; // subdir non-accessible
+ const bfs::path src_noperms_subdir1 = "/noperms/a/b/c/d/noperms_subdir1"; // child subdir non-accessible
+ const bfs::path src_noperms_subdir2 = "/noperms/noperms_subdir2/a"; // parent subdir non-accessible
+
+ const bfs::path src_symlink_at_root0 = "/symlink0";
+ const bfs::path src_symlink_at_root1 = "/symlink1";
+ const bfs::path src_symlink_at_root2 = "/symlink2";
+ const bfs::path src_symlink_at_subdir0 = "/foo/bar/baz/symlink0";
+ const bfs::path src_symlink_at_subdir1 = "/foo/bar/baz/symlink1";
+ const bfs::path src_symlink_at_subdir2 = "/foo/bar/baz/symlink2";
+
+ const bfs::path dst_root = "/";
+ const bfs::path dst_subdir0 = "/output_dir0";
+ const bfs::path dst_subdir1 = "/output_dir1";
+ const bfs::path dst_file_at_root0 = "/file0"; // same basename
+ const bfs::path dst_file_at_root1 = "/file1"; // different basename
+ const bfs::path dst_file_at_subdir0 = "/a/b/c/d/file0"; // same fullname
+ const bfs::path dst_file_at_subdir1 = "/a/b/c/d/file1"; // same parents, different basename
+ const bfs::path dst_file_at_subdir2 = "/e/f/g/h/i/file0"; // different parents, same basename
+ const bfs::path dst_file_at_subdir3 = "/e/f/g/h/i/file1"; // different fullname
+
+ // create input data
+ env.add_to_namespace(nsid0, src_file_at_root, 40000);
+ env.add_to_namespace(nsid0, src_file_at_subdir, 80000);
+ env.add_to_namespace(nsid0, src_subdir0);
+ env.add_to_namespace(nsid0, src_subdir1);
+ env.add_to_namespace(nsid0, src_empty_dir);
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir0 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir1 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ // create input data with special permissions
+ auto p = env.add_to_namespace(nsid0, src_noperms_file0, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file1, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file2, 0);
+ env.remove_access(p.parent_path());
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir1);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir2);
+ env.remove_access(p.parent_path());
+
+ // add symlinks to the namespace
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_root0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_root1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_root2);
+
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_subdir0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_subdir1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_subdir2);
+
+ // manually create a symlink leading outside namespace 0
+ boost::system::error_code ec;
+ const bfs::path out_symlink = "/out_symlink";
+ bfs::create_symlink(dst_mnt, src_mnt / out_symlink, ec);
+ REQUIRE(!ec);
+
+ // create required output directories
+ env.add_to_namespace(nsid1, dst_subdir1);
+
+ /**********************************************************************/
+ /* begin tests */
+ /**********************************************************************/
+ // - trying to copy a non-existing file
+ WHEN("copying a non-existing NORNS_LOCAL_PATH file") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_invalid_file.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == ENOENT);
+ }
+ }
+ }
+ }
+
+ // - trying to copy a non-existing directory
+ WHEN("copying a non-existing NORNS_LOCAL_PATH directory") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_invalid_dir.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == ENOENT);
+ }
+ }
+ }
+ }
+
+ // - trying to copy an empty directory
+ WHEN("copying an empty NORNS_LOCAL_PATH directory") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_empty_dir.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_SUCCESS and ENOENT are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+ REQUIRE(stats.st_task_error == NORNS_SUCCESS);
+ REQUIRE(stats.st_sys_errno == 0);
+
+ REQUIRE(bfs::exists(dst_mnt / dst_file_at_root0));
+ }
+ }
+ }
+ }
+
+//FIXME: DISABLED in CI until impersonation is implemented or capabilities can be added to the docker service
+#ifdef __SETCAP_TESTS__
+
+ // - trying to copy a file from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH file from \"/\" without appropriate "
+ "permissions to access it") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_noperms_file0.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL "
+ "are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a file from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH file from a subdir without "
+ "appropriate permissions to access it") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_noperms_file1.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a file from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH file from a subdir without "
+ "appropriate permissions to access a parent") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_noperms_file2.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL "
+ "are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a subdir from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH subdir from \"/\" without "
+ "appropriate permissions to access it") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir0.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL "
+ "are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a subdir from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH subdir from another subdir "
+ "without appropriate permissions to access it") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir1.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a subdir from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH subdir from another subdir without "
+ "appropriate permissions to access a parent") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir2.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL "
+ "are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // symlink leading out of namespace
+ WHEN("copying a NORNS_LOCAL_PATH through a symbolic link that leads "
+ "out of the SRC namespace") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ out_symlink.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == ENOENT);
+ }
+ }
+ }
+ }
+#endif
+
+ env.notify_success();
+ }
+}
+
+/******************************************************************************/
+/* tests for push transfers (single files) */
+/******************************************************************************/
+SCENARIO("copy local POSIX file to remote POSIX file (admin)",
+ "[api::nornsctl_submit_push_to_posix_file]") {
+ GIVEN("a running urd instance") {
+
+ /**********************************************************************/
+ /* setup common environment */
+ /**********************************************************************/
+ test_env env(false);
+
+ const char* nsid0 = "tmp0";
+ const char* nsid1 = "tmp1";
+ const char* remote_host = "127.0.0.1:42000";
+ bfs::path src_mnt, dst_mnt;
+
+ // create namespaces
+ std::tie(std::ignore, src_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid1, "mnt/tmp1", 16384);
+
+ // define input names
+ const bfs::path src_file_at_root = "/file0";
+ const bfs::path src_file_at_subdir = "/a/b/c/d/file0";
+ const bfs::path src_invalid_file = "/a/b/c/d/does_not_exist_file0";
+ const bfs::path src_invalid_dir = "/a/b/c/d/does_not_exist_dir0";
+ const bfs::path src_subdir0 = "/input_dir0";
+ const bfs::path src_subdir1 = "/input_dir0/a/b/c/input_dir1";
+ const bfs::path src_empty_dir = "/empty_dir0";
+
+ const bfs::path src_noperms_file0 = "/noperms_file0";
+ const bfs::path src_noperms_file1 = "/noperms/a/b/c/d/noperms_file0"; // parents accessible
+ const bfs::path src_noperms_file2 = "/noperms/noperms_subdir0/file0"; // parents non-accessible
+ const bfs::path src_noperms_subdir0 = "/noperms_subdir0"; // subdir non-accessible
+ const bfs::path src_noperms_subdir1 = "/noperms/a/b/c/d/noperms_subdir1"; // child subdir non-accessible
+ const bfs::path src_noperms_subdir2 = "/noperms/noperms_subdir2/a"; // parent subdir non-accessible
+
+ const bfs::path src_symlink_at_root0 = "/symlink0";
+ const bfs::path src_symlink_at_root1 = "/symlink1";
+ const bfs::path src_symlink_at_root2 = "/symlink2";
+ const bfs::path src_symlink_at_subdir0 = "/foo/bar/baz/symlink0";
+ const bfs::path src_symlink_at_subdir1 = "/foo/bar/baz/symlink1";
+ const bfs::path src_symlink_at_subdir2 = "/foo/bar/baz/symlink2";
+
+ const bfs::path dst_root = "/";
+ const bfs::path dst_subdir0 = "/output_dir0";
+ const bfs::path dst_subdir1 = "/output_dir1";
+ const bfs::path dst_file_at_root0 = "/file0"; // same basename
+ const bfs::path dst_file_at_root1 = "/file1"; // different basename
+ const bfs::path dst_file_at_subdir0 = "/a/b/c/d/file0"; // same fullname
+ const bfs::path dst_file_at_subdir1 = "/a/b/c/d/file1"; // same parents, different basename
+ const bfs::path dst_file_at_subdir2 = "/e/f/g/h/i/file0"; // different parents, same basename
+ const bfs::path dst_file_at_subdir3 = "/e/f/g/h/i/file1"; // different fullname
+
+ // create input data
+ env.add_to_namespace(nsid0, src_file_at_root, 40000);
+ env.add_to_namespace(nsid0, src_file_at_subdir, 80000);
+ env.add_to_namespace(nsid0, src_subdir0);
+ env.add_to_namespace(nsid0, src_subdir1);
+ env.add_to_namespace(nsid0, src_empty_dir);
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir0 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir1 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ // create input data with special permissions
+ auto p = env.add_to_namespace(nsid0, src_noperms_file0, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file1, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file2, 0);
+ env.remove_access(p.parent_path());
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir1);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir2);
+ env.remove_access(p.parent_path());
+
+ // add symlinks to the namespace
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_root0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_root1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_root2);
+
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_subdir0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_subdir1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_subdir2);
+
+ // manually create a symlink leading outside namespace 0
+ boost::system::error_code ec;
+ const bfs::path out_symlink = "/out_symlink";
+ bfs::create_symlink(dst_mnt, src_mnt / out_symlink, ec);
+ REQUIRE(!ec);
+
+ // create required output directories
+ env.add_to_namespace(nsid1, dst_subdir1);
+
+
+ /**********************************************************************/
+ /* begin tests */
+ /**********************************************************************/
+ // cp -r ns0://file0.txt
+ // -> ns1:// = ns1://file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from SRC namespace's root to "
+ "another NORNS_REMOTE_PATH at DST namespace's root "
+ "(keeping the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file_at_root.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_root);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://file0.txt
+ // -> ns1://file1.txt = ns1://file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from SRC namespace's root to "
+ "another NORNS_LOCAL_PATH at DST namespace's root "
+ "(changing the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file_at_root.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_root);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_root1);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../d/file0.txt
+ // -> ns1://file0.txt = ns1://file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a SRC namespace's subdir "
+ "to another NORNS_LOCAL_PATH at DST namespace's root (keeping "
+ "the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file_at_subdir.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../d/file0.txt
+ // -> ns1://file1.txt = ns1://file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a SRC namespace's subdir "
+ "to another NORNS_LOCAL_PATH at DST namespace's root (changing "
+ "the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_subdir.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_root1);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://file0.txt
+ // -> ns1://a/b/c/.../file0.txt = ns1://a/b/c/.../file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from SRC namespace's root to "
+ "another NORNS_LOCAL_PATH at a DST namespace's subdir "
+ "(keeping the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file_at_root.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_subdir0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_root);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_subdir0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://file0.txt
+ // -> ns1://a/b/c/.../file1.txt = ns1://a/b/c/.../file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from SRC namespace's root to "
+ "another NORNS_LOCAL_PATH at a DST namespace's subdir "
+ "(changing the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file_at_root.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_subdir1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_root);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_subdir1);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../file0.txt
+ // -> ns1://a/b/c/.../file0.txt = ns1://a/b/c/.../file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a SRC namespace's subdir "
+ "to another NORNS_LOCAL_PATH at a DST namespace's subdir "
+ "(keeping the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file_at_subdir.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_subdir0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_subdir0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../file0.txt
+ // -> ns1://a/b/c/.../file1.txt = ns1://a/b/c/.../file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a SRC namespace's subdir "
+ "to another NORNS_LOCAL_PATH at a DST namespace's subdir "
+ "(changing the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file_at_subdir.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_subdir1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_subdir1);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../file0.txt
+ // -> ns1://e/f/g/.../file0.txt = ns1://e/f/g/.../file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a SRC namespace's subdir "
+ "to another NORNS_LOCAL_PATH at a DST namespace's subdir "
+ "(changing the parents names)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file_at_subdir.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_subdir2.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_subdir2);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../file0.txt
+ // -> ns1://e/f/g/.../file1.txt = ns1://e/f/g/.../file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a SRC namespace's subdir "
+ "to another NORNS_LOCAL_PATH at a DST namespace's subdir "
+ "(changing the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file_at_subdir.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_subdir3.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_subdir3);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ env.notify_success();
+ }
+}
+
+/******************************************************************************/
+/* tests for push transfers (directories) */
+/******************************************************************************/
+SCENARIO("copy local POSIX file to remote POSIX subdir (admin)",
+ "[api::nornsctl_submit_push_to_posix_subdir]") {
+ GIVEN("a running urd instance") {
+
+ /**********************************************************************/
+ /* setup common environment */
+ /**********************************************************************/
+ test_env env(false);
+
+ const char* nsid0 = "tmp0";
+ const char* nsid1 = "tmp1";
+ const char* remote_host = "127.0.0.1:42000";
+ bfs::path src_mnt, dst_mnt;
+
+ // create namespaces
+ std::tie(std::ignore, src_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid1, "mnt/tmp1", 16384);
+
+ // define input names
+ const bfs::path src_file_at_root = "/file0";
+ const bfs::path src_file_at_subdir = "/a/b/c/d/file0";
+ const bfs::path src_invalid_file = "/a/b/c/d/does_not_exist_file0";
+ const bfs::path src_invalid_dir = "/a/b/c/d/does_not_exist_dir0";
+ const bfs::path src_subdir0 = "/input_dir0";
+ const bfs::path src_subdir1 = "/input_dir0/a/b/c/input_dir1";
+ const bfs::path src_empty_dir = "/empty_dir0";
+
+ const bfs::path src_noperms_file0 = "/noperms_file0";
+ const bfs::path src_noperms_file1 = "/noperms/a/b/c/d/noperms_file0"; // parents accessible
+ const bfs::path src_noperms_file2 = "/noperms/noperms_subdir0/file0"; // parents non-accessible
+ const bfs::path src_noperms_subdir0 = "/noperms_subdir0"; // subdir non-accessible
+ const bfs::path src_noperms_subdir1 = "/noperms/a/b/c/d/noperms_subdir1"; // child subdir non-accessible
+ const bfs::path src_noperms_subdir2 = "/noperms/noperms_subdir2/a"; // parent subdir non-accessible
+
+ const bfs::path src_symlink_at_root0 = "/symlink0";
+ const bfs::path src_symlink_at_root1 = "/symlink1";
+ const bfs::path src_symlink_at_root2 = "/symlink2";
+ const bfs::path src_symlink_at_subdir0 = "/foo/bar/baz/symlink0";
+ const bfs::path src_symlink_at_subdir1 = "/foo/bar/baz/symlink1";
+ const bfs::path src_symlink_at_subdir2 = "/foo/bar/baz/symlink2";
+
+ const bfs::path dst_root = "/";
+ const bfs::path dst_subdir0 = "/output_dir0";
+ const bfs::path dst_subdir1 = "/output_dir1";
+ const bfs::path dst_file_at_root0 = "/file0"; // same basename
+ const bfs::path dst_file_at_root1 = "/file1"; // different basename
+ const bfs::path dst_file_at_subdir0 = "/a/b/c/d/file0"; // same fullname
+ const bfs::path dst_file_at_subdir1 = "/a/b/c/d/file1"; // same parents, different basename
+ const bfs::path dst_file_at_subdir2 = "/e/f/g/h/i/file0"; // different parents, same basename
+ const bfs::path dst_file_at_subdir3 = "/e/f/g/h/i/file1"; // different fullname
+
+ // create input data
+ env.add_to_namespace(nsid0, src_file_at_root, 40000);
+ env.add_to_namespace(nsid0, src_file_at_subdir, 80000);
+ env.add_to_namespace(nsid0, src_subdir0);
+ env.add_to_namespace(nsid0, src_subdir1);
+ env.add_to_namespace(nsid0, src_empty_dir);
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir0 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir1 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ // create input data with special permissions
+ auto p = env.add_to_namespace(nsid0, src_noperms_file0, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file1, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file2, 0);
+ env.remove_access(p.parent_path());
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir1);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir2);
+ env.remove_access(p.parent_path());
+
+ // add symlinks to the namespace
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_root0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_root1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_root2);
+
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_subdir0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_subdir1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_subdir2);
+
+ // manually create a symlink leading outside namespace 0
+ boost::system::error_code ec;
+ const bfs::path out_symlink = "/out_symlink";
+ bfs::create_symlink(dst_mnt, src_mnt / out_symlink, ec);
+ REQUIRE(!ec);
+
+
+ // create required output directories
+ env.add_to_namespace(nsid1, dst_subdir1);
+
+ /**********************************************************************/
+ /* begin tests */
+ /**********************************************************************/
+ // cp -r /a/contents.* -> / = /contents.*
+ WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from SRC "
+ "namespace's root to DST namespace's root\n"
+ " cp -r /a/contents.* -> / = /contents.* ") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir0.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_root.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Copied files are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_root);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r /a/b/c/.../contents.* -> / = /contents.*
+ WHEN("copying the contents of a NORNS_LOCAL_PATH arbitrary subdir to "
+ "DST namespace's root\n"
+ " cp -r /a/b/c/.../contents.* -> / = /contents.*") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir1.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_root.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Copied files are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_root);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r /a/contents.* -> /c = /c/contents.*
+ // (c did not exist previously)
+ WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from SRC "
+ "namespace's root to another NORNS_REMOTE_PATH subdir at DST "
+ "namespace's root while changing its name\n"
+ " cp -r /a/contents.* -> /c = /c/contents.*") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir0.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_subdir0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Copied files are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_subdir0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r /a/contents.* -> /c = /c/contents.*
+ // (c did exist previously)
+ WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from SRC "
+ "namespace's root to another NORNS_REMOTE_PATH subdir at DST "
+ "namespace's root while changing its name\n"
+ " cp -r /a/contents.* -> /c / /c/contents.*") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir0.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_subdir1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Copied files are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_subdir1);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r /a/b/c/.../contents.* -> /c = /c/a/b/c/.../contents.*
+ // (c did not exist previously)
+ WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from SRC "
+ "namespace's root to a NORNS_REMOTE_PATH subdir at DST "
+ "namespace's root while changing its name\n"
+ "cp -r /a/b/c/.../contents.* -> /c = /c/a/b/c/.../contents.*") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir1.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_subdir0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Copied files are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_subdir0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r /a/b/c/.../contents.* -> /c = /c/a/b/c/.../contents.*
+ // (c did exist previously)
+ WHEN("copying the contents of a NORNS_LOCAL_PATH subdir from SRC "
+ "namespace's root to another NORNS_REMOTE_PATH subdir at DST "
+ "namespace's root while changing its name:"
+ " cp -r /a/b/c/.../contents.* -> /c = /c/a/b/c/.../contents.*") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_subdir1.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_subdir1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Copied files are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_subdir1);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ env.notify_success();
+ }
+}
+
+/******************************************************************************/
+/* tests for push transfers (memory buffers) */
+/******************************************************************************/
+SCENARIO("copy local memory region to remote POSIX file (admin)",
+ "[api::nornsctl_submit_push_memory_to_posix_file]") {
+
+ GIVEN("a running urd instance") {
+
+ /**********************************************************************/
+ /* setup common environment */
+ /**********************************************************************/
+ test_env env;
+
+ const char* nsid0 = "tmp0";
+ const char* remote_host = "127.0.0.1:42000";
+ bfs::path dst_mnt;
+
+ // create namespaces
+ std::tie(std::ignore, dst_mnt) = env.create_namespace(nsid0, "mnt/tmp0", 16384);
+
+ // create input data buffer (around 40MiBs)
+ std::vector input_data(10000000, 42);
+ void* region_addr = input_data.data();
+ size_t region_size = input_data.size() * sizeof(int);
+
+ // output names
+ const bfs::path dst_file_at_root0 = "/file0";
+ const bfs::path dst_file_at_subdir0 = "/a/b/c/d/file0";
+ const bfs::path dst_root = "/";
+ const bfs::path dst_subdir0 = "/output_dir0/"; // existing
+ const bfs::path dst_subdir1 = "/output_dir0"; // existing but does not look as a directory
+ const bfs::path dst_subdir2 = "/output_dir0/a/b/c/d/"; // existing
+ const bfs::path dst_subdir3 = "/output_dir0/a/b/c/d"; // existing but does not look as a directory
+ const bfs::path dst_subdir4 = "/output_dir1/"; // non-existing
+ const bfs::path dst_subdir5 = "/output_dir1/a/b/c/d/"; // non-existing
+
+ // create required output directories
+ env.add_to_namespace(nsid0, dst_subdir0);
+ env.add_to_namespace(nsid0, dst_subdir2);
+
+ //
+ WHEN("copying a valid memory region to a NORNS_REMOTE_PATH file "
+ "located at DST's namespace root '/'") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() return NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Output file contains buffer data") {
+
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid0, dst_file_at_root0);
+
+ REQUIRE(compare(input_data, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ WHEN("copying a valid memory region to a NORNS_REMOTE_PATH file "
+ "located at a DST's subdir") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ dst_file_at_subdir0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("nornsctl_wait() return NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Output file contains buffer data") {
+
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid0, dst_file_at_subdir0);
+
+ REQUIRE(compare(input_data, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ env.notify_success();
+ }
+
+#ifndef USE_REAL_DAEMON
+ GIVEN("a non-running urd instance") {
+ WHEN("attempting to request a transfer") {
+
+ norns_iotask_t task = NORNSCTL_IOTASK(
+ NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH("nvml0://", "/a/b/c/"),
+ NORNS_REMOTE_PATH("nvml0://", "node1", "/a/b/d/"));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ECONNFAILED is returned") {
+ REQUIRE(rv == NORNS_ECONNFAILED);
+ }
+ }
+ }
+#endif
+}
+
+
+/******************************************************************************/
+/* tests for push transfers (memory buffers, errors) */
+/******************************************************************************/
+SCENARIO("errors copying local memory region to remote POSIX file (admin)",
+ "[api::nornsctl_submit_push_memory_to_posix_file_errors]") {
+
+ GIVEN("a running urd instance") {
+
+ /**********************************************************************/
+ /* setup common environment */
+ /**********************************************************************/
+ test_env env;
+
+ const char* nsid0 = "tmp0";
+ const char* remote_host = "127.0.0.1:42000";
+ bfs::path dst_mnt;
+
+ // create namespaces
+ std::tie(std::ignore, dst_mnt) = env.create_namespace(nsid0, "mnt/tmp0", 16384);
+
+ // create input data buffer (around 40MiBs)
+ std::vector input_data(10000000, 42);
+ void* region_addr = input_data.data();
+ size_t region_size = input_data.size() * sizeof(int);
+
+ // output names
+ const bfs::path dst_file_at_root0 = "/file0";
+ const bfs::path dst_file_at_subdir0 = "/a/b/c/d/file0";
+ const bfs::path dst_root = "/";
+ const bfs::path dst_subdir0 = "/output_dir0/"; // existing
+ const bfs::path dst_subdir1 = "/output_dir0"; // existing but does not look as a directory
+ const bfs::path dst_subdir2 = "/output_dir0/a/b/c/d/"; // existing
+ const bfs::path dst_subdir3 = "/output_dir0/a/b/c/d"; // existing but does not look as a directory
+ const bfs::path dst_subdir4 = "/output_dir1/"; // non-existing
+ const bfs::path dst_subdir5 = "/output_dir1/a/b/c/d/"; // non-existing
+
+ // create required output directories
+ env.add_to_namespace(nsid0, dst_subdir0);
+ env.add_to_namespace(nsid0, dst_subdir2);
+
+ //TODO
+ // - copy a valid but removed memory region (cannot control => undefined behavior)
+ // - providing a non-existing directory path (i.e. finished with /) as output name
+ // - providing an existing path that points to a directory as output name
+ WHEN("copying an invalid memory region to a NORNS_REMOTE_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION((void*) 0x42, 42000),
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() return NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EFAULT") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == EFAULT);
+ }
+ }
+ }
+ }
+
+ WHEN("copying a valid memory region to a NORNS_REMOTE_PATH at "
+ "DST's /") {
+
+ // create input data buffer
+ std::vector input_data(100, 42);
+ void* region_addr = input_data.data();
+ size_t region_size = input_data.size() * sizeof(int);
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ dst_root.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_EBADARGS") {
+ REQUIRE(rv == NORNS_EBADARGS);
+ }
+ }
+
+ WHEN("copying a valid memory region to a NORNS_REMOTE_PATH existing "
+ "directory at DST's /") {
+
+ // create input data buffer
+ std::vector input_data(100, 42);
+ void* region_addr = input_data.data();
+ size_t region_size = input_data.size() * sizeof(int);
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ dst_subdir0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_EBADARGS") {
+ REQUIRE(rv == NORNS_EBADARGS);
+ }
+ }
+
+ WHEN("copying a valid memory region to a NORNS_REMOTE_PATH existing "
+ "directory at / that does not look like a directory") {
+
+ // create input data buffer
+ std::vector input_data(100, 42);
+ void* region_addr = input_data.data();
+ size_t region_size = input_data.size() * sizeof(int);
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ dst_subdir1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() return NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EISDIR") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == EISDIR);
+ }
+ }
+ }
+ }
+
+ WHEN("copying a valid memory region to a NORNS_REMOTE_PATH existing "
+ "directory at a DST's arbitary subdir") {
+
+ // create input data buffer
+ std::vector input_data(100, 42);
+ void* region_addr = input_data.data();
+ size_t region_size = input_data.size() * sizeof(int);
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ dst_subdir2.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_EBADARGS") {
+ REQUIRE(rv == NORNS_EBADARGS);
+ }
+ }
+
+ WHEN("copying a valid memory region to a NORNS_REMOTE_PATH existing "
+ "directory at a DST's arbitary subdir that does not look like "
+ "a directory") {
+
+ // create input data buffer
+ std::vector input_data(100, 42);
+ void* region_addr = input_data.data();
+ size_t region_size = input_data.size() * sizeof(int);
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ dst_subdir3.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() return NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EISDIR") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == EISDIR);
+ }
+ }
+ }
+ }
+
+
+ // i.e. a destination path that 'looks like' a directory
+ WHEN("copying a valid memory region to a NORNS_REMOTE_PATH "
+ "corresponding to a non-existing directory at DST's /") {
+
+ // create input data buffer
+ std::vector input_data(100, 42);
+ void* region_addr = input_data.data();
+ size_t region_size = input_data.size() * sizeof(int);
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ dst_subdir4.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_EBADARGS") {
+ REQUIRE(rv == NORNS_EBADARGS);
+ }
+ }
+
+ WHEN("copying a valid memory region to a NORNS_REMOTE_PATH "
+ "non-existing arbitrary subdir at DST") {
+
+ // create input data buffer
+ std::vector input_data(100, 42);
+ void* region_addr = input_data.data();
+ size_t region_size = input_data.size() * sizeof(int);
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(region_addr, region_size),
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ dst_subdir5.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_EBADARGS") {
+ REQUIRE(rv == NORNS_EBADARGS);
+ }
+ }
+
+
+ env.notify_success();
+ }
+
+#ifndef USE_REAL_DAEMON
+ GIVEN("a non-running urd instance") {
+ WHEN("attempting to request a transfer") {
+
+ norns_iotask_t task = NORNSCTL_IOTASK(
+ NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH("nvml0://", "/a/b/c/"),
+ NORNS_REMOTE_PATH("nvml0://", "node1", "/a/b/d/"));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ECONNFAILED is returned") {
+ REQUIRE(rv == NORNS_ECONNFAILED);
+ }
+ }
+ }
+#endif
+}
+
+/******************************************************************************/
+/* tests for push transfers (links) */
+/******************************************************************************/
+SCENARIO("copy local POSIX path to remote POSIX path involving links (admin)",
+ "[api::nornsctl_submit_push_links]") {
+ GIVEN("a running urd instance") {
+
+ /**********************************************************************/
+ /* setup common environment */
+ /**********************************************************************/
+ test_env env(false);
+
+ const char* nsid0 = "tmp0";
+ const char* nsid1 = "tmp1";
+ const char* remote_host = "127.0.0.1:42000";
+ bfs::path src_mnt, dst_mnt;
+
+ // create namespaces
+ std::tie(std::ignore, src_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid1, "mnt/tmp1", 16384);
+
+ // define input names
+ const bfs::path src_file_at_root = "/file0";
+ const bfs::path src_file_at_subdir = "/a/b/c/d/file0";
+ const bfs::path src_invalid_file = "/a/b/c/d/does_not_exist_file0";
+ const bfs::path src_invalid_dir = "/a/b/c/d/does_not_exist_dir0";
+ const bfs::path src_subdir0 = "/input_dir0";
+ const bfs::path src_subdir1 = "/input_dir0/a/b/c/input_dir1";
+ const bfs::path src_empty_dir = "/empty_dir0";
+
+ const bfs::path src_noperms_file0 = "/noperms_file0";
+ const bfs::path src_noperms_file1 = "/noperms/a/b/c/d/noperms_file0"; // parents accessible
+ const bfs::path src_noperms_file2 = "/noperms/noperms_subdir0/file0"; // parents non-accessible
+ const bfs::path src_noperms_subdir0 = "/noperms_subdir0"; // subdir non-accessible
+ const bfs::path src_noperms_subdir1 = "/noperms/a/b/c/d/noperms_subdir1"; // child subdir non-accessible
+ const bfs::path src_noperms_subdir2 = "/noperms/noperms_subdir2/a"; // parent subdir non-accessible
+
+ const bfs::path src_symlink_at_root0 = "/symlink0";
+ const bfs::path src_symlink_at_root1 = "/symlink1";
+ const bfs::path src_symlink_at_root2 = "/symlink2";
+ const bfs::path src_symlink_at_subdir0 = "/foo/bar/baz/symlink0";
+ const bfs::path src_symlink_at_subdir1 = "/foo/bar/baz/symlink1";
+ const bfs::path src_symlink_at_subdir2 = "/foo/bar/baz/symlink2";
+
+ const bfs::path dst_root = "/";
+ const bfs::path dst_subdir0 = "/output_dir0";
+ const bfs::path dst_subdir1 = "/output_dir1";
+ const bfs::path dst_file_at_root0 = "/file0"; // same basename
+ const bfs::path dst_file_at_root1 = "/file1"; // different basename
+ const bfs::path dst_file_at_subdir0 = "/a/b/c/d/file0"; // same fullname
+ const bfs::path dst_file_at_subdir1 = "/a/b/c/d/file1"; // same parents, different basename
+ const bfs::path dst_file_at_subdir2 = "/e/f/g/h/i/file0"; // different parents, same basename
+ const bfs::path dst_file_at_subdir3 = "/e/f/g/h/i/file1"; // different fullname
+
+ // create input data
+ env.add_to_namespace(nsid0, src_file_at_root, 40000);
+ env.add_to_namespace(nsid0, src_file_at_subdir, 80000);
+ env.add_to_namespace(nsid0, src_subdir0);
+ env.add_to_namespace(nsid0, src_subdir1);
+ env.add_to_namespace(nsid0, src_empty_dir);
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir0 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir1 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ // create input data with special permissions
+ auto p = env.add_to_namespace(nsid0, src_noperms_file0, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file1, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file2, 0);
+ env.remove_access(p.parent_path());
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir1);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir2);
+ env.remove_access(p.parent_path());
+
+ // add symlinks to the namespace
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_root0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_root1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_root2);
+
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_subdir0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_subdir1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_subdir2);
+
+ // manually create a symlink leading outside namespace 0
+ boost::system::error_code ec;
+ const bfs::path out_symlink = "/out_symlink";
+ bfs::create_symlink(dst_mnt, src_mnt / out_symlink, ec);
+ REQUIRE(!ec);
+
+
+ // create required output directories
+ env.add_to_namespace(nsid1, dst_subdir1);
+
+ /**********************************************************************/
+ /* begin tests */
+ /**********************************************************************/
+ WHEN("copying a single NORNS_LOCAL_PATH file from SRC namespace's '/' "
+ "through a symlink also located at '/'" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_root0.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_symlink_at_root0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ WHEN("copying a single NORNS_LOCAL_PATH subdir from SRC "
+ "namespace's '/' through a symlink also located at '/'" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_root1.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Directories are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_symlink_at_root1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ WHEN("copying a single NORNS_LOCAL_PATH arbitrary subdir"
+ "through a symlink also located at '/'" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_root2.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Directories are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_symlink_at_root2);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ WHEN("copying a single NORNS_LOCAL_PATH file from SRC namespace's '/' "
+ "through a symlink located in a subdir" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_subdir0.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0,
+ src_symlink_at_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ WHEN("copying a single NORNS_LOCAL_PATH subdir from SRC "
+ "namespace's '/' through a symlink also located at subdir" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_subdir1.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Directories are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0,
+ src_symlink_at_subdir1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ WHEN("copying a single NORNS_LOCAL_PATH arbitrary subdir"
+ "through a symlink also located at a subdir" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_subdir2.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Directories are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0,
+ src_symlink_at_subdir2);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ env.notify_success();
+ }
+}
+
+/******************************************************************************/
+/* tests for pull transfers (errors) */
+/******************************************************************************/
+SCENARIO("errors copying remote POSIX path to local POSIX path (admin)",
+ "[api::nornsctl_submit_pull_errors]") {
+ GIVEN("a running urd instance") {
+
+ /**********************************************************************/
+ /* setup common environment */
+ /**********************************************************************/
+ test_env env(false);
+
+ const char* nsid0 = "tmp0";
+ const char* nsid1 = "tmp1";
+ const char* remote_host = "127.0.0.1:42000";
+ bfs::path src_mnt, dst_mnt;
+
+ // create namespaces
+ std::tie(std::ignore, src_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid1, "mnt/tmp1", 16384);
+
+ // define input names
+ const bfs::path src_file_at_root = "/file0";
+ const bfs::path src_file_at_subdir = "/a/b/c/d/file0";
+ const bfs::path src_invalid_file = "/a/b/c/d/does_not_exist_file0";
+ const bfs::path src_invalid_dir = "/a/b/c/d/does_not_exist_dir0";
+ const bfs::path src_subdir0 = "/input_dir0";
+ const bfs::path src_subdir1 = "/input_dir0/a/b/c/input_dir1";
+ const bfs::path src_empty_dir = "/empty_dir0";
+
+ const bfs::path src_noperms_file0 = "/noperms_file0";
+ const bfs::path src_noperms_file1 = "/noperms/a/b/c/d/noperms_file0"; // parents accessible
+ const bfs::path src_noperms_file2 = "/noperms/noperms_subdir0/file0"; // parents non-accessible
+ const bfs::path src_noperms_subdir0 = "/noperms_subdir0"; // subdir non-accessible
+ const bfs::path src_noperms_subdir1 = "/noperms/a/b/c/d/noperms_subdir1"; // child subdir non-accessible
+ const bfs::path src_noperms_subdir2 = "/noperms/noperms_subdir2/a"; // parent subdir non-accessible
+
+ const bfs::path src_symlink_at_root0 = "/symlink0";
+ const bfs::path src_symlink_at_root1 = "/symlink1";
+ const bfs::path src_symlink_at_root2 = "/symlink2";
+ const bfs::path src_symlink_at_subdir0 = "/foo/bar/baz/symlink0";
+ const bfs::path src_symlink_at_subdir1 = "/foo/bar/baz/symlink1";
+ const bfs::path src_symlink_at_subdir2 = "/foo/bar/baz/symlink2";
+
+ const bfs::path dst_root = "/";
+ const bfs::path dst_subdir0 = "/output_dir0";
+ const bfs::path dst_subdir1 = "/output_dir1";
+ const bfs::path dst_file_at_root0 = "/file0"; // same basename
+ const bfs::path dst_file_at_root1 = "/file1"; // different basename
+ const bfs::path dst_file_at_subdir0 = "/a/b/c/d/file0"; // same fullname
+ const bfs::path dst_file_at_subdir1 = "/a/b/c/d/file1"; // same parents, different basename
+ const bfs::path dst_file_at_subdir2 = "/e/f/g/h/i/file0"; // different parents, same basename
+ const bfs::path dst_file_at_subdir3 = "/e/f/g/h/i/file1"; // different fullname
+
+ // create input data
+ env.add_to_namespace(nsid0, src_file_at_root, 40000);
+ env.add_to_namespace(nsid0, src_file_at_subdir, 80000);
+ env.add_to_namespace(nsid0, src_subdir0);
+ env.add_to_namespace(nsid0, src_subdir1);
+ env.add_to_namespace(nsid0, src_empty_dir);
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir0 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir1 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ // create input data with special permissions
+ auto p = env.add_to_namespace(nsid0, src_noperms_file0, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file1, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file2, 0);
+ env.remove_access(p.parent_path());
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir1);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir2);
+ env.remove_access(p.parent_path());
+
+ // add symlinks to the namespace
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_root0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_root1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_root2);
+
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_subdir0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_subdir1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_subdir2);
+
+ // manually create a symlink leading outside namespace 0
+ boost::system::error_code ec;
+ const bfs::path out_symlink = "/out_symlink";
+ bfs::create_symlink(dst_mnt, src_mnt / out_symlink, ec);
+ REQUIRE(!ec);
+
+ // create required output directories
+ env.add_to_namespace(nsid1, dst_subdir1);
+
+ /**********************************************************************/
+ /* begin tests */
+ /**********************************************************************/
+ // - trying to copy a non-existing file
+ WHEN("copying a non-existing NORNS_LOCAL_PATH file") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_invalid_file.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == ENOENT);
+ }
+ }
+ }
+ }
+
+ // - trying to copy a non-existing directory
+ WHEN("copying a non-existing NORNS_LOCAL_PATH directory") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_invalid_dir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == ENOENT);
+ }
+ }
+ }
+ }
+
+ // - trying to copy an empty directory
+ WHEN("copying an empty NORNS_LOCAL_PATH directory") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_empty_dir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_SUCCESS and ENOENT are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+ REQUIRE(stats.st_task_error == NORNS_SUCCESS);
+ REQUIRE(stats.st_sys_errno == 0);
+
+ REQUIRE(bfs::exists(dst_mnt / dst_file_at_root0));
+ }
+ }
+ }
+ }
+
+//FIXME: DISABLED in CI until impersonation is implemented or capabilities can be added to the docker service
+#ifdef __SETCAP_TESTS__
+
+#if 0 // not adapted to pull semantics
+ // - trying to copy a file from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH file from \"/\" without appropriate "
+ "permissions to access it") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_noperms_file0.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL "
+ "are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a file from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH file from a subdir without "
+ "appropriate permissions to access it") {
+
+ norns_op_t task_op = NORNS_IOTASK_COPY;
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_noperms_file1.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a file from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH file from a subdir without "
+ "appropriate permissions to access a parent") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_noperms_file2.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL "
+ "are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a subdir from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH subdir from \"/\" without "
+ "appropriate permissions to access it") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir0.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL "
+ "are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a subdir from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH subdir from another subdir "
+ "without appropriate permissions to access it") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir1.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a subdir from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH subdir from another subdir without "
+ "appropriate permissions to access a parent") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir2.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL "
+ "are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // symlink leading out of namespace
+ WHEN("copying a NORNS_LOCAL_PATH through a symbolic link that leads "
+ "out of the SRC namespace") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ out_symlink.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ remote_host,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == ENOENT);
+ }
+ }
+ }
+ }
+#endif
+#endif
+ env.notify_success();
+ }
+}
+
+/******************************************************************************/
+/* tests for pull transfers (single files) */
+/******************************************************************************/
+SCENARIO("copy remote POSIX file to local POSIX file (admin)",
+ "[api::nornsctl_submit_pull_to_posix_file]") {
+ GIVEN("a running urd instance") {
+
+ /**********************************************************************/
+ /* setup common environment */
+ /**********************************************************************/
+ test_env env(false);
+
+ const char* nsid0 = "tmp0";
+ const char* nsid1 = "tmp1";
+ const char* remote_host = "127.0.0.1:42000";
+ bfs::path src_mnt, dst_mnt;
+
+ // create namespaces
+ std::tie(std::ignore, src_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid1, "mnt/tmp1", 16384);
+
+ // define input names
+ const bfs::path src_file_at_root = "/file0";
+ const bfs::path src_file_at_subdir = "/a/b/c/d/file0";
+ const bfs::path src_invalid_file = "/a/b/c/d/does_not_exist_file0";
+ const bfs::path src_invalid_dir = "/a/b/c/d/does_not_exist_dir0";
+ const bfs::path src_subdir0 = "/input_dir0";
+ const bfs::path src_subdir1 = "/input_dir0/a/b/c/input_dir1";
+ const bfs::path src_empty_dir = "/empty_dir0";
+
+ const bfs::path src_noperms_file0 = "/noperms_file0";
+ const bfs::path src_noperms_file1 = "/noperms/a/b/c/d/noperms_file0"; // parents accessible
+ const bfs::path src_noperms_file2 = "/noperms/noperms_subdir0/file0"; // parents non-accessible
+ const bfs::path src_noperms_subdir0 = "/noperms_subdir0"; // subdir non-accessible
+ const bfs::path src_noperms_subdir1 = "/noperms/a/b/c/d/noperms_subdir1"; // child subdir non-accessible
+ const bfs::path src_noperms_subdir2 = "/noperms/noperms_subdir2/a"; // parent subdir non-accessible
+
+ const bfs::path src_symlink_at_root0 = "/symlink0";
+ const bfs::path src_symlink_at_root1 = "/symlink1";
+ const bfs::path src_symlink_at_root2 = "/symlink2";
+ const bfs::path src_symlink_at_subdir0 = "/foo/bar/baz/symlink0";
+ const bfs::path src_symlink_at_subdir1 = "/foo/bar/baz/symlink1";
+ const bfs::path src_symlink_at_subdir2 = "/foo/bar/baz/symlink2";
+
+ const bfs::path dst_root = "/";
+ const bfs::path dst_subdir0 = "/output_dir0";
+ const bfs::path dst_subdir1 = "/output_dir1";
+ const bfs::path dst_file_at_root0 = "/file0"; // same basename
+ const bfs::path dst_file_at_root1 = "/file1"; // different basename
+ const bfs::path dst_file_at_subdir0 = "/a/b/c/d/file0"; // same fullname
+ const bfs::path dst_file_at_subdir1 = "/a/b/c/d/file1"; // same parents, different basename
+ const bfs::path dst_file_at_subdir2 = "/e/f/g/h/i/file0"; // different parents, same basename
+ const bfs::path dst_file_at_subdir3 = "/e/f/g/h/i/file1"; // different fullname
+
+ // create input data
+ env.add_to_namespace(nsid0, src_file_at_root, 40000);
+ env.add_to_namespace(nsid0, src_file_at_subdir, 80000);
+ env.add_to_namespace(nsid0, src_subdir0);
+ env.add_to_namespace(nsid0, src_subdir1);
+ env.add_to_namespace(nsid0, src_empty_dir);
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir0 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir1 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ // create input data with special permissions
+ auto p = env.add_to_namespace(nsid0, src_noperms_file0, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file1, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file2, 0);
+ env.remove_access(p.parent_path());
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir1);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir2);
+ env.remove_access(p.parent_path());
+
+ // add symlinks to the namespace
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_root0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_root1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_root2);
+
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_subdir0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_subdir1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_subdir2);
+
+ // manually create a symlink leading outside namespace 0
+ boost::system::error_code ec;
+ const bfs::path out_symlink = "/out_symlink";
+ bfs::create_symlink(dst_mnt, src_mnt / out_symlink, ec);
+ REQUIRE(!ec);
+
+
+ // create required output directories
+ env.add_to_namespace(nsid1, dst_subdir1);
+
+ /**********************************************************************/
+ /* begin tests */
+ /**********************************************************************/
+ // cp -r ns0://file0.txt
+ // -> ns1:// = ns1://file0.txt
+ WHEN("copying a single NORNS_REMOTE_PATH from SRC namespace's root to "
+ "another NORNS_LOCAL_PATH at DST namespace's root "
+ "(keeping the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_file_at_root.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() return NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_root);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://file0.txt
+ // -> ns1://file1.txt = ns1://file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from SRC namespace's root to "
+ "another NORNS_LOCAL_PATH at DST namespace's root "
+ "(changing the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_file_at_root.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() return NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_file_at_root);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root1);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../d/file0.txt
+ // -> ns1://file0.txt = ns1://file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a SRC namespace's subdir "
+ "to another NORNS_LOCAL_PATH at DST namespace's root (keeping "
+ "the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../d/file0.txt
+ // -> ns1://file1.txt = ns1://file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a SRC namespace's subdir "
+ "to another NORNS_LOCAL_PATH at DST namespace's root (changing "
+ "the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_root1);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://file0.txt
+ // -> ns1://a/b/c/.../file0.txt = ns1://a/b/c/.../file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from SRC namespace's root to "
+ "another NORNS_LOCAL_PATH at a DST namespace's subdir "
+ "(keeping the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_file_at_root.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(nsid0,
+ src_file_at_root);
+ bfs::path dst =
+ env.get_from_namespace(nsid1,
+ dst_file_at_subdir0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://file0.txt
+ // -> ns1://a/b/c/.../file1.txt = ns1://a/b/c/.../file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from SRC namespace's root to "
+ "another NORNS_LOCAL_PATH at a DST namespace's subdir "
+ "(changing the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_file_at_root.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_root);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_subdir1);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../file0.txt
+ // -> ns1://a/b/c/.../file0.txt = ns1://a/b/c/.../file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a SRC namespace's subdir "
+ "to another NORNS_LOCAL_PATH at a DST namespace's subdir "
+ "(keeping the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_subdir0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../file0.txt
+ // -> ns1://a/b/c/.../file1.txt = ns1://a/b/c/.../file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a SRC namespace's subdir "
+ "to another NORNS_LOCAL_PATH at a DST namespace's subdir "
+ "(changing the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_subdir1);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../file0.txt
+ // -> ns1://e/f/g/.../file0.txt = ns1://e/f/g/.../file0.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a SRC namespace's subdir "
+ "to another NORNS_LOCAL_PATH at a DST namespace's subdir "
+ "(changing the parents names)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir2.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_subdir2);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r ns0://a/b/c/.../file0.txt
+ // -> ns1://e/f/g/.../file1.txt = ns1://e/f/g/.../file1.txt
+ WHEN("copying a single NORNS_LOCAL_PATH from a SRC namespace's subdir "
+ "to another NORNS_LOCAL_PATH at a DST namespace's subdir "
+ "(changing the name)") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_file_at_subdir.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_subdir3.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+ bfs::path src =
+ env.get_from_namespace(
+ nsid0, src_file_at_subdir);
+ bfs::path dst =
+ env.get_from_namespace(
+ nsid1, dst_file_at_subdir3);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ env.notify_success();
+ }
+}
+
+/******************************************************************************/
+/* tests for pull transfers (directories) */
+/******************************************************************************/
+SCENARIO("copy remote POSIX subdir to local POSIX subdir (admin)",
+ "[api::nornsctl_submit_pull_to_posix_subdir]") {
+ GIVEN("a running urd instance") {
+
+ /**********************************************************************/
+ /* setup common environment */
+ /**********************************************************************/
+ test_env env(false);
+
+ const char* nsid0 = "tmp0";
+ const char* nsid1 = "tmp1";
+ const char* remote_host = "127.0.0.1:42000";
+ bfs::path src_mnt, dst_mnt;
+
+ // create namespaces
+ std::tie(std::ignore, src_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid1, "mnt/tmp1", 16384);
+
+ // define input names
+ const bfs::path src_file_at_root = "/file0";
+ const bfs::path src_file_at_subdir = "/a/b/c/d/file0";
+ const bfs::path src_invalid_file = "/a/b/c/d/does_not_exist_file0";
+ const bfs::path src_invalid_dir = "/a/b/c/d/does_not_exist_dir0";
+ const bfs::path src_subdir0 = "/input_dir0";
+ const bfs::path src_subdir1 = "/input_dir0/a/b/c/input_dir1";
+ const bfs::path src_empty_dir = "/empty_dir0";
+
+ const bfs::path src_noperms_file0 = "/noperms_file0";
+ const bfs::path src_noperms_file1 = "/noperms/a/b/c/d/noperms_file0"; // parents accessible
+ const bfs::path src_noperms_file2 = "/noperms/noperms_subdir0/file0"; // parents non-accessible
+ const bfs::path src_noperms_subdir0 = "/noperms_subdir0"; // subdir non-accessible
+ const bfs::path src_noperms_subdir1 = "/noperms/a/b/c/d/noperms_subdir1"; // child subdir non-accessible
+ const bfs::path src_noperms_subdir2 = "/noperms/noperms_subdir2/a"; // parent subdir non-accessible
+
+ const bfs::path src_symlink_at_root0 = "/symlink0";
+ const bfs::path src_symlink_at_root1 = "/symlink1";
+ const bfs::path src_symlink_at_root2 = "/symlink2";
+ const bfs::path src_symlink_at_subdir0 = "/foo/bar/baz/symlink0";
+ const bfs::path src_symlink_at_subdir1 = "/foo/bar/baz/symlink1";
+ const bfs::path src_symlink_at_subdir2 = "/foo/bar/baz/symlink2";
+
+ const bfs::path dst_root = "/";
+ const bfs::path dst_subdir0 = "/output_dir0";
+ const bfs::path dst_subdir1 = "/output_dir1";
+ const bfs::path dst_file_at_root0 = "/file0"; // same basename
+ const bfs::path dst_file_at_root1 = "/file1"; // different basename
+ const bfs::path dst_file_at_subdir0 = "/a/b/c/d/file0"; // same fullname
+ const bfs::path dst_file_at_subdir1 = "/a/b/c/d/file1"; // same parents, different basename
+ const bfs::path dst_file_at_subdir2 = "/e/f/g/h/i/file0"; // different parents, same basename
+ const bfs::path dst_file_at_subdir3 = "/e/f/g/h/i/file1"; // different fullname
+
+ // create input data
+ env.add_to_namespace(nsid0, src_file_at_root, 40000);
+ env.add_to_namespace(nsid0, src_file_at_subdir, 80000);
+ env.add_to_namespace(nsid0, src_subdir0);
+ env.add_to_namespace(nsid0, src_subdir1);
+ env.add_to_namespace(nsid0, src_empty_dir);
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir0 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir1 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ // create input data with special permissions
+ auto p = env.add_to_namespace(nsid0, src_noperms_file0, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file1, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file2, 0);
+ env.remove_access(p.parent_path());
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir1);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir2);
+ env.remove_access(p.parent_path());
+
+ // add symlinks to the namespace
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_root0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_root1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_root2);
+
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_subdir0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_subdir1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_subdir2);
+
+ // manually create a symlink leading outside namespace 0
+ boost::system::error_code ec;
+ const bfs::path out_symlink = "/out_symlink";
+ bfs::create_symlink(dst_mnt, src_mnt / out_symlink, ec);
+ REQUIRE(!ec);
+
+
+ // create required output directories
+ env.add_to_namespace(nsid1, dst_subdir1);
+
+ // cp -r /a/contents.* -> / = /contents.*
+ WHEN("copying the contents of a NORNS_REMOTE_PATH subdir from SRC "
+ "namespace's root to a NORNS_LOCAL_PATH at DST namespace's root\n"
+ " cp -r /a/contents.* -> / = /contents.* ") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_subdir0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_root.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Copied subdirs are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_root);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r /a/b/c/.../contents.* -> / = /contents.*
+ WHEN("copying the contents of a NORNS_REMOTE_PATH arbitrary subdir to "
+ "a NORNS_LOCAL_PATH at DST namespace's root\n"
+ " cp -r /a/b/c/.../contents.* -> / = /contents.*") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_subdir1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_root.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Copied subdirs are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_root);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r /a/contents.* -> /c = /c/contents.*
+ // (c did not exist previously)
+ WHEN("copying the contents of a NORNS_REMOTE_PATH subdir from SRC "
+ "namespace's root to another NORNS_LOCAL_PATH subdir at DST "
+ "namespace's root while changing its name\n"
+ " cp -r /a/contents.* -> /c = /c/contents.*") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_subdir0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_subdir0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Copied subdirs are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_subdir0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r /a/contents.* -> /c = /c/contents.*
+ // (c did exist previously)
+ WHEN("copying the contents of a NORNS_REMOTE_PATH subdir from SRC "
+ "namespace's root to another NORNS_LOCAL_PATH subdir at DST "
+ "namespace's root while changing its name\n"
+ " cp -r /a/contents.* -> /c / /c/contents.*") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_subdir0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_subdir1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Copied files are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_subdir1);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r /a/b/c/.../contents.* -> /c = /c/a/b/c/.../contents.*
+ // (c did not exist previously)
+ WHEN("copying the contents of a NORNS_REMOTE_PATH subdir from SRC "
+ "namespace's root to a NORNS_LOCAL_PATH subdir at DST "
+ "namespace's root while changing its name\n"
+ "cp -r /a/b/c/.../contents.* -> /c = /c/a/b/c/.../contents.*") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_subdir1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_subdir0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Copied files are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_subdir0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ // cp -r /a/b/c/.../contents.* -> /c = /c/a/b/c/.../contents.*
+ // (c did exist previously)
+ WHEN("copying the contents of a NORNS_REMOTE_PATH subdir from SRC "
+ "namespace's root to another NORNS_LOCAL_PATH subdir at DST "
+ "namespace's root while changing its name:"
+ " cp -r /a/b/c/.../contents.* -> /c = /c/a/b/c/.../contents.*") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_subdir1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_subdir1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Copied files are identical to original") {
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_subdir1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_subdir1);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ env.notify_success();
+ }
+
+#ifndef USE_REAL_DAEMON
+ GIVEN("a non-running urd instance") {
+ WHEN("attempting to request a transfer") {
+
+ norns_iotask_t task = NORNSCTL_IOTASK(
+ NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH("nvml0://", "/a/b/c/"),
+ NORNS_REMOTE_PATH("nvml0://", "node1", "/a/b/d/"));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_ECONNFAILED") {
+ REQUIRE(rv == NORNS_ECONNFAILED);
+ }
+ }
+ }
+#endif
+}
+
+/******************************************************************************/
+/* tests for pull transfers (links) */
+/******************************************************************************/
+SCENARIO("copy remote POSIX path to local POSIX path involving links (admin)",
+ "[api::nornsctl_submit_pull_links]") {
+ GIVEN("a running urd instance") {
+
+ /**********************************************************************/
+ /* setup common environment */
+ /**********************************************************************/
+ test_env env(false);
+
+ const char* nsid0 = "tmp0";
+ const char* nsid1 = "tmp1";
+ const char* remote_host = "127.0.0.1:42000";
+ bfs::path src_mnt, dst_mnt;
+
+ // create namespaces
+ std::tie(std::ignore, src_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid1, "mnt/tmp1", 16384);
+
+ // define input names
+ const bfs::path src_file_at_root = "/file0";
+ const bfs::path src_file_at_subdir = "/a/b/c/d/file0";
+ const bfs::path src_invalid_file = "/a/b/c/d/does_not_exist_file0";
+ const bfs::path src_invalid_dir = "/a/b/c/d/does_not_exist_dir0";
+ const bfs::path src_subdir0 = "/input_dir0";
+ const bfs::path src_subdir1 = "/input_dir0/a/b/c/input_dir1";
+ const bfs::path src_empty_dir = "/empty_dir0";
+
+ const bfs::path src_noperms_file0 = "/noperms_file0";
+ const bfs::path src_noperms_file1 = "/noperms/a/b/c/d/noperms_file0"; // parents accessible
+ const bfs::path src_noperms_file2 = "/noperms/noperms_subdir0/file0"; // parents non-accessible
+ const bfs::path src_noperms_subdir0 = "/noperms_subdir0"; // subdir non-accessible
+ const bfs::path src_noperms_subdir1 = "/noperms/a/b/c/d/noperms_subdir1"; // child subdir non-accessible
+ const bfs::path src_noperms_subdir2 = "/noperms/noperms_subdir2/a"; // parent subdir non-accessible
+
+ const bfs::path src_symlink_at_root0 = "/symlink0";
+ const bfs::path src_symlink_at_root1 = "/symlink1";
+ const bfs::path src_symlink_at_root2 = "/symlink2";
+ const bfs::path src_symlink_at_subdir0 = "/foo/bar/baz/symlink0";
+ const bfs::path src_symlink_at_subdir1 = "/foo/bar/baz/symlink1";
+ const bfs::path src_symlink_at_subdir2 = "/foo/bar/baz/symlink2";
+
+ const bfs::path dst_root = "/";
+ const bfs::path dst_subdir0 = "/output_dir0";
+ const bfs::path dst_subdir1 = "/output_dir1";
+ const bfs::path dst_file_at_root0 = "/file0"; // same basename
+ const bfs::path dst_file_at_root1 = "/file1"; // different basename
+ const bfs::path dst_file_at_subdir0 = "/a/b/c/d/file0"; // same fullname
+ const bfs::path dst_file_at_subdir1 = "/a/b/c/d/file1"; // same parents, different basename
+ const bfs::path dst_file_at_subdir2 = "/e/f/g/h/i/file0"; // different parents, same basename
+ const bfs::path dst_file_at_subdir3 = "/e/f/g/h/i/file1"; // different fullname
+
+ // create input data
+ env.add_to_namespace(nsid0, src_file_at_root, 40000);
+ env.add_to_namespace(nsid0, src_file_at_subdir, 80000);
+ env.add_to_namespace(nsid0, src_subdir0);
+ env.add_to_namespace(nsid0, src_subdir1);
+ env.add_to_namespace(nsid0, src_empty_dir);
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir0 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir1 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ // create input data with special permissions
+ auto p = env.add_to_namespace(nsid0, src_noperms_file0, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file1, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file2, 0);
+ env.remove_access(p.parent_path());
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir1);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir2);
+ env.remove_access(p.parent_path());
+
+ // add symlinks to the namespace
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_root0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_root1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_root2);
+
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_subdir0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_subdir1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_subdir2);
+
+ // manually create a symlink leading outside namespace 0
+ boost::system::error_code ec;
+ const bfs::path out_symlink = "/out_symlink";
+ bfs::create_symlink(dst_mnt, src_mnt / out_symlink, ec);
+ REQUIRE(!ec);
+
+
+ // create required output directories
+ env.add_to_namespace(nsid1, dst_subdir1);
+
+ /**********************************************************************/
+ /* begin tests */
+ /**********************************************************************/
+ WHEN("copying a single NORNS_REMOTE_PATH file from SRC namespace's '/' "
+ "through a symlink also located at '/'" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_symlink_at_root0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_symlink_at_root0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ WHEN("copying a single NORNS_REMOTE_PATH subdir from SRC "
+ "namespace's '/' through a symlink also located at '/'" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_symlink_at_root1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Directories are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_symlink_at_root1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ WHEN("copying a single NORNS_REMOTE_PATH arbitrary subdir"
+ "through a symlink also located at '/'" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_symlink_at_root2.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Directories are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0, src_symlink_at_root2);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ WHEN("copying a single NORNS_REMOTE_PATH file from SRC namespace's '/' "
+ "through a symlink located in a subdir" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_symlink_at_subdir0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Files are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0,
+ src_symlink_at_subdir0);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_files(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ WHEN("copying a single NORNS_REMOTE_PATH subdir from SRC "
+ "namespace's '/' through a symlink also located at subdir" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_symlink_at_subdir1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Directories are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0,
+ src_symlink_at_subdir1);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ WHEN("copying a single NORNS_REMOTE_PATH arbitrary subdir"
+ "through a symlink also located at a subdir" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ remote_host,
+ src_symlink_at_subdir2.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_EFINISHED") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHED);
+
+ THEN("Directories are equal") {
+
+ bfs::path src =
+ env.get_from_namespace(nsid0,
+ src_symlink_at_subdir2);
+ bfs::path dst =
+ env.get_from_namespace(nsid1, dst_file_at_root0);
+
+ REQUIRE(compare_directories(src, dst) == true);
+ }
+ }
+ }
+ }
+ }
+
+ env.notify_success();
+ }
+}
diff --git a/tests/api-ctl-remove-local-data.cpp b/tests/api-ctl-remove-local-data.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..73fdf06695aa02ea2e4a114f1a878bfdd20b16bf
--- /dev/null
+++ b/tests/api-ctl-remove-local-data.cpp
@@ -0,0 +1,774 @@
+/*************************************************************************
+ * Copyright (C) 2017-2018 Barcelona Supercomputing Center *
+ * Centro Nacional de Supercomputacion *
+ * All rights reserved. *
+ * *
+ * This file is part of the NORNS Data Scheduler, a service that allows *
+ * other programs to start, track and manage asynchronous transfers of *
+ * data resources transfers requests between different storage backends. *
+ * *
+ * See AUTHORS file in the top level directory for information *
+ * regarding developers and contributors. *
+ * *
+ * The NORNS 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 NORNS 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 the NORNS Data Scheduler. If not, see *
+ * . *
+ *************************************************************************/
+
+#include "nornsctl.h"
+#include "test-env.hpp"
+#include "compare-files.hpp"
+#include "catch.hpp"
+
+namespace bfs = boost::filesystem;
+
+SCENARIO("remove a local POSIX file (admin)",
+ "[api::nornsctl_submit_remove_local_posix_files]") {
+ GIVEN("a running urd instance") {
+
+ test_env env;
+
+ const char* nsid0 = "tmp0";
+ const char* nsid1 = "tmp1";
+ bfs::path src_mnt, dst_mnt;
+
+ // create namespaces
+ std::tie(std::ignore, src_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid1, "mnt/tmp1", 16384);
+
+ // define input names
+ const bfs::path src_file_at_root = "/file0";
+ const bfs::path src_file_at_subdir = "/a/b/c/d/file0";
+ const bfs::path src_invalid_file = "/a/b/c/d/does_not_exist_file0";
+ const bfs::path src_invalid_dir = "/a/b/c/d/does_not_exist_dir0";
+ const bfs::path src_subdir0 = "/input_dir0";
+ const bfs::path src_subdir1 = "/input_dir0/a/b/c/input_dir1";
+ const bfs::path src_empty_dir = "/empty_dir0";
+
+ const bfs::path src_noperms_file0 = "/noperms_file0";
+ const bfs::path src_noperms_file1 = "/noperms/a/b/c/d/noperms_file0"; // parents accessible
+ const bfs::path src_noperms_file2 = "/noperms/noperms_subdir0/file0"; // parents non-accessible
+ const bfs::path src_noperms_subdir0 = "/noperms_subdir0"; // subdir non-accessible
+ const bfs::path src_noperms_subdir1 = "/noperms/a/b/c/d/noperms_subdir1"; // child subdir non-accessible
+ const bfs::path src_noperms_subdir2 = "/noperms/noperms_subdir2/a"; // parent subdir non-accessible
+
+ const bfs::path src_symlink_at_root0 = "/symlink0";
+ const bfs::path src_symlink_at_root1 = "/symlink1";
+ const bfs::path src_symlink_at_root2 = "/symlink2";
+ const bfs::path src_symlink_at_subdir0 = "/foo/bar/baz/symlink0";
+ const bfs::path src_symlink_at_subdir1 = "/foo/bar/baz/symlink1";
+ const bfs::path src_symlink_at_subdir2 = "/foo/bar/baz/symlink2";
+
+ const bfs::path dst_root = "/";
+ const bfs::path dst_subdir0 = "/output_dir0";
+ const bfs::path dst_subdir1 = "/output_dir1";
+ const bfs::path dst_file_at_root0 = "/file0"; // same basename
+ const bfs::path dst_file_at_root1 = "/file1"; // different basename
+ const bfs::path dst_file_at_subdir0 = "/a/b/c/d/file0"; // same fullname
+ const bfs::path dst_file_at_subdir1 = "/a/b/c/d/file1"; // same parents, different basename
+ const bfs::path dst_file_at_subdir2 = "/e/f/g/h/i/file0"; // different parents, same basename
+ const bfs::path dst_file_at_subdir3 = "/e/f/g/h/i/file1"; // different fullname
+
+ // create input data
+ env.add_to_namespace(nsid0, src_file_at_root, 4096);
+ env.add_to_namespace(nsid0, src_file_at_subdir, 8192);
+ env.add_to_namespace(nsid0, src_subdir0);
+ env.add_to_namespace(nsid0, src_subdir1);
+ env.add_to_namespace(nsid0, src_empty_dir);
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir0 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ for(int i=0; i<10; ++i) {
+ const bfs::path p{src_subdir1 / ("file" + std::to_string(i))};
+ env.add_to_namespace(nsid0, p, 4096+i*10);
+ }
+
+ // create input data with special permissions
+ auto p = env.add_to_namespace(nsid0, src_noperms_file0, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file1, 0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_file2, 0);
+ env.remove_access(p.parent_path());
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir0);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir1);
+ env.remove_access(p);
+
+ p = env.add_to_namespace(nsid0, src_noperms_subdir2);
+ env.remove_access(p.parent_path());
+
+ // add symlinks to the namespace
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_root0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_root1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_root2);
+
+ env.add_to_namespace(nsid0, src_file_at_root, src_symlink_at_subdir0);
+ env.add_to_namespace(nsid0, src_subdir0, src_symlink_at_subdir1);
+ env.add_to_namespace(nsid0, src_subdir1, src_symlink_at_subdir2);
+
+ // manually create a symlink leading outside namespace 0
+ boost::system::error_code ec;
+ const bfs::path out_symlink = "/out_symlink";
+ bfs::create_symlink(dst_mnt, src_mnt / out_symlink, ec);
+ REQUIRE(!ec);
+
+
+ // create required output directories
+ env.add_to_namespace(nsid1, dst_subdir1);
+
+ /**********************************************************************/
+ /* tests for error conditions */
+ /**********************************************************************/
+ // - trying to remove a non-existing file
+ WHEN("removing a non-existing NORNS_LOCAL_PATH file") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0, src_invalid_file.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "ENOENT") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == ENOENT);
+ }
+ }
+ }
+ }
+
+
+ // - trying to remove a non-existing directory
+ WHEN("removing a non-existing NORNS_LOCAL_PATH directory") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0, src_invalid_dir.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "ENOENT") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(stats.st_sys_errno == ENOENT);
+ }
+ }
+ }
+ }
+
+//FIXME: DISABLED in CI until impersonation is implemented or capabilities can be added to the docker service
+#ifdef __SETCAP_TESTS__
+
+ // - trying to copy a file from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH file from \"/\" without appropriate "
+ "permissions to access it") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_file0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a file from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH file from a subdir without "
+ "appropriate permissions to access it") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_noperms_file1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a file from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH file from a subdir without "
+ "appropriate permissions to access a parent") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_noperms_file2.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a subdir from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH subdir from \"/\" without "
+ "appropriate permissions to access it") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a subdir from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH subdir from another subdir without "
+ "appropriate permissions to access it") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+
+ // - trying to copy a subdir from namespace root with invalid access permissions
+ WHEN("copying a NORNS_LOCAL_PATH subdir from another subdir without "
+ "appropriate permissions to access a parent") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir2.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("nornsctl_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
+ REQUIRE(stats.st_task_error == NORNS_ESYSTEMERROR);
+ REQUIRE(( (stats.st_sys_errno == EACCES) ||
+ (stats.st_sys_errno == EPERM ) ||
+ (stats.st_sys_errno == EINVAL) ));
+ }
+ }
+ }
+ }
+#endif
+
+ /**********************************************************************/
+ /* tests for single files */
+ /**********************************************************************/
+ // rm ns0://file0.txt
+ WHEN("removing a single NORNS_LOCAL_PATH from src namespace's root") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0, src_file_at_root.c_str()));
+ const bfs::path p = env.get_from_namespace(nsid0, src_file_at_root);
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("File no longer exists") {
+ REQUIRE(!bfs::exists(p));
+ }
+ }
+ }
+ }
+
+ // rm ns0://a/b/c/.../d/file0.txt
+ WHEN("removing a single NORNS_LOCAL_PATH from a src namespace's "
+ "subdir") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_subdir.c_str()));
+ const bfs::path p =
+ env.get_from_namespace(nsid0, src_file_at_subdir);
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("File no longer exists") {
+ REQUIRE(!bfs::exists(p));
+ }
+ }
+ }
+ }
+
+ /**********************************************************************/
+ /* tests for directories */
+ /**********************************************************************/
+ // rm -r /a/contents.*
+ WHEN("removing the contents of a NORNS_LOCAL_PATH subdir from src "
+ "namespace's root") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0, src_subdir0.c_str()));
+ const bfs::path p = env.get_from_namespace(nsid0, src_subdir0);
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Directory no longer exists") {
+ REQUIRE(!bfs::exists(p));
+ }
+ }
+ }
+ }
+
+ // rm -r /a/b/c/.../contents.*
+ WHEN("removing the contents of a NORNS_LOCAL_PATH arbitrary subdir") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0, src_subdir1.c_str()));
+ const bfs::path p = env.get_from_namespace(nsid0, src_subdir1);
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Directory no longer exists") {
+ REQUIRE(!bfs::exists(p));
+ }
+ }
+ }
+ }
+
+ WHEN("removing an empty NORNS_LOCAL_PATH directory") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0, src_empty_dir.c_str()));
+ const bfs::path p = env.get_from_namespace(nsid0, src_empty_dir);
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("Directory no longer exists") {
+ REQUIRE(!bfs::exists(p));
+ }
+ }
+ }
+ }
+
+
+ /**********************************************************************/
+ /* tests for soft links */
+ /**********************************************************************/
+ WHEN("removing a single NORNS_LOCAL_PATH file from src namespace's '/' "
+ "through a symlink also located at '/'" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_root0.c_str()));
+ const bfs::path p =
+ env.get_from_namespace(nsid0, "/") / src_symlink_at_root0;
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("symlink no longer exists and original file is left "
+ "intact") {
+ REQUIRE(!bfs::exists(p));
+ REQUIRE(bfs::exists(
+ env.get_from_namespace(nsid0, src_file_at_root)));
+ }
+ }
+ }
+ }
+
+ WHEN("removing a single NORNS_LOCAL_PATH arbitrary subdir"
+ "through a symlink located at '/'" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_root2.c_str()));
+ const bfs::path p =
+ env.get_from_namespace(nsid0, "/") / src_symlink_at_root2;
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("symlink no longer exists and original file is left "
+ "intact") {
+ REQUIRE(!bfs::exists(p));
+ REQUIRE(bfs::exists(
+ env.get_from_namespace(nsid0, src_subdir1)));
+ }
+ }
+ }
+ }
+
+ WHEN("removing a single NORNS_LOCAL_PATH file from src namespace's '/' "
+ "through a symlink located in a subdir" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_subdir0.c_str()));
+ const bfs::path p =
+ env.get_from_namespace(nsid0, "/") / src_symlink_at_subdir0;
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("symlink no longer exists and original file is left "
+ "intact") {
+ REQUIRE(!bfs::exists(p));
+ REQUIRE(bfs::exists(
+ env.get_from_namespace(nsid0, src_file_at_root)));
+ }
+ }
+ }
+ }
+
+ WHEN("removing a single NORNS_LOCAL_PATH subdir from src namespace's "
+ "'/' through a symlink also located at subdir") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_subdir1.c_str()));
+ const bfs::path p =
+ env.get_from_namespace(nsid0, "/") / src_symlink_at_subdir1;
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("symlink no longer exists and original file is left "
+ "intact") {
+ REQUIRE(!bfs::exists(p));
+ REQUIRE(bfs::exists(env.get_from_namespace(nsid0, src_subdir0)));
+ }
+ }
+ }
+ }
+
+ WHEN("removing a single NORNS_LOCAL_PATH arbitrary subdir"
+ "through a symlink also located at a subdir" ) {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_subdir2.c_str()));
+ const bfs::path p =
+ env.get_from_namespace(nsid0, "/") / src_symlink_at_subdir2;
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ // wait until the task completes
+ rv = nornsctl_wait(&task);
+
+ THEN("nornsctl_wait() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ THEN("symlink no longer exists and original file is left "
+ "intact") {
+ REQUIRE(!bfs::exists(p));
+ REQUIRE(bfs::exists(
+ env.get_from_namespace(nsid0, src_subdir1)));
+ }
+ }
+ }
+ }
+
+ env.notify_success();
+ }
+
+
+#ifndef USE_REAL_DAEMON
+ GIVEN("a non-running urd instance") {
+ WHEN("attempting to request a transfer") {
+
+ norns_iotask_t task = NORNSCTL_IOTASK(
+ NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH("nvml0://", "/a/b/c/"),
+ NORNS_REMOTE_PATH("nvml0://", "node1", "/a/b/d/"));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ECONNFAILED is returned") {
+ REQUIRE(rv == NORNS_ECONNFAILED);
+ }
+ }
+ }
+#endif
+}
+
diff --git a/tests/api-ctl-task-init.cpp b/tests/api-ctl-task-init.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5a1bbb6f839c55fade684b360ef38db196a283ad
--- /dev/null
+++ b/tests/api-ctl-task-init.cpp
@@ -0,0 +1,224 @@
+/*************************************************************************
+ * Copyright (C) 2017-2018 Barcelona Supercomputing Center *
+ * Centro Nacional de Supercomputacion *
+ * All rights reserved. *
+ * *
+ * This file is part of the NORNS Data Scheduler, a service that allows *
+ * other programs to start, track and manage asynchronous transfers of *
+ * data resources transfers requests between different storage backends. *
+ * *
+ * See AUTHORS file in the top level directory for information *
+ * regarding developers and contributors. *
+ * *
+ * The NORNS 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 NORNS 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 the NORNS Data Scheduler. If not, see *
+ * . *
+ *************************************************************************/
+
+#include
+#include "nornsctl.h"
+#include "catch.hpp"
+
+SCENARIO("initialize a task with nornsctl_iotask_init",
+ "[api::nornsctl_iotask_init]") {
+
+ GIVEN("invalid task information") {
+ WHEN("initializing a task with NULL src and dst") {
+
+ norns_iotask_t task;
+ norns_op_t task_op = NORNS_IOTASK_COPY;
+
+ nornsctl_iotask_init(&task, task_op, NULL, NULL);
+
+ AND_THEN("task is set to 0") {
+ norns_iotask_t dummy;
+ memset(&dummy, 0, sizeof(dummy));
+ REQUIRE(memcmp(&task, &dummy, sizeof(norns_iotask_t)) == 0);
+ }
+ }
+ }
+
+ GIVEN("invalid task information") {
+ WHEN("initializing a task with a NULL src") {
+
+ norns_iotask_t task;
+ norns_op_t task_op = NORNS_IOTASK_COPY;
+
+ const char* dst_nsid = "tmp://";
+ const char* dst_path = "/a/b/c";
+ norns_resource_t dst = NORNS_LOCAL_PATH(dst_nsid, dst_path);
+
+ nornsctl_iotask_init(&task, task_op, NULL, &dst);
+
+ THEN("task is set to 0") {
+ norns_iotask_t dummy;
+ memset(&dummy, 0, sizeof(dummy));
+ REQUIRE(memcmp(&task, &dummy, sizeof(norns_iotask_t)) == 0);
+ }
+ }
+ }
+
+ GIVEN("valid task information") {
+ WHEN("initializing a task with src=NORNS_PROCESS_MEMORY and "
+ "dst=NORNS_POSIX_PATH | R_LOCAL") {
+
+ norns_op_t task_op = NORNS_IOTASK_COPY;
+ void* src_addr = (void*) 0xdeadbeef;
+ size_t src_size = (size_t) 42;
+ const char* dst_nsid = "tmp://";
+ const char* dst_path = "/a/b/c";
+
+ norns_resource_t src = NORNS_MEMORY_REGION(src_addr, src_size);
+
+ REQUIRE(src.r_buffer.b_addr == src_addr);
+ REQUIRE(src.r_buffer.b_size == src_size);
+
+ norns_resource_t dst = NORNS_LOCAL_PATH(dst_nsid, dst_path);
+
+ REQUIRE(strcmp(dst.r_posix_path.p_nsid, dst_nsid) == 0);
+ REQUIRE(dst.r_posix_path.p_host == NULL);
+ REQUIRE(strcmp(dst.r_posix_path.p_path, dst_path) == 0);
+
+ norns_iotask_t task;
+ nornsctl_iotask_init(&task, task_op, &src, &dst);
+
+ THEN("the norns_task structure is initialized as expected") {
+ REQUIRE(task.t_id == 0);
+ REQUIRE(task.t_op == task_op);
+ REQUIRE(memcmp(&task.t_src, &src,
+ sizeof(norns_resource_t)) == 0);
+ REQUIRE(memcmp(&task.t_dst, &dst,
+ sizeof(norns_resource_t)) == 0);
+ }
+ }
+ }
+
+ GIVEN("valid task information") {
+ WHEN("initializing a task with src=NORNS_PROCESS_MEMORY and "
+ "dst=NORNS_POSIX_PATH | R_REMOTE") {
+
+ norns_op_t task_op = NORNS_IOTASK_COPY;
+ void* src_addr = (void*) 0xdeadbeef;
+ size_t src_size = (size_t) 42;
+ const char* dst_nsid = "tmp://";
+ const char* dst_host = "node0";
+ const char* dst_path = "/a/b/c";
+
+ norns_resource_t src = NORNS_MEMORY_REGION(src_addr, src_size);
+
+ REQUIRE(src.r_buffer.b_addr == src_addr);
+ REQUIRE(src.r_buffer.b_size == src_size);
+
+ norns_resource_t dst = NORNS_REMOTE_PATH(dst_nsid, dst_host, dst_path);
+
+ REQUIRE(strcmp(dst.r_posix_path.p_nsid, dst_nsid) == 0);
+ REQUIRE(strcmp(dst.r_posix_path.p_host, dst_host) == 0);
+ REQUIRE(strcmp(dst.r_posix_path.p_path, dst_path) == 0);
+
+ norns_iotask_t task;
+ nornsctl_iotask_init(&task, task_op, &src, &dst);
+
+ THEN("the norns_task structure is initialized as expected") {
+ REQUIRE(task.t_id == 0);
+ REQUIRE(task.t_op == task_op);
+ REQUIRE(memcmp(&task.t_src, &src,
+ sizeof(norns_resource_t)) == 0);
+ REQUIRE(memcmp(&task.t_dst, &dst,
+ sizeof(norns_resource_t)) == 0);
+ }
+ }
+ }
+}
+
+SCENARIO("initialize a task with NORNSCTL_IOTASK", "[api::NORNSCTL_IOTASK]") {
+
+ GIVEN("valid task information") {
+ WHEN("initializing a task with src=NORNS_MEMORY_REGION and "
+ "dst=NORNS_LOCAL_PATH") {
+
+ norns_op_t task_op = NORNS_IOTASK_COPY;
+ void* src_addr = (void*) 0xdeadbeef;
+ size_t src_size = (size_t) 42;
+ const char* dst_nsid = "tmp://";
+ const char* dst_path = "/a/b/c";
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(task_op,
+ NORNS_MEMORY_REGION(src_addr, src_size),
+ NORNS_LOCAL_PATH(dst_nsid, dst_path));
+
+ THEN("the norns_task structure is initialized as expected") {
+ REQUIRE(task.t_id == 0);
+ REQUIRE(task.t_op == task_op);
+
+ REQUIRE(task.t_src.r_buffer.b_addr == src_addr);
+
+ REQUIRE(strcmp(task.t_dst.r_posix_path.p_nsid, dst_nsid) == 0);
+ REQUIRE(strcmp(task.t_dst.r_posix_path.p_path, dst_path) == 0);
+ }
+ }
+
+ WHEN("initializing a task with src=NORNS_PROCESS_MEMORY and "
+ "dst=NORNS_REMOTE_PATH") {
+ norns_op_t task_op = NORNS_IOTASK_COPY;
+ void* src_addr = (void*) 0xdeadbeef;
+ size_t src_size = (size_t) 42;
+ const char* dst_nsid = "tmp://";
+ const char* dst_host = "node0";
+ const char* dst_path = "/a/b/c";
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(task_op,
+ NORNS_MEMORY_REGION(src_addr, src_size),
+ NORNS_REMOTE_PATH(dst_nsid, dst_host, dst_path));
+
+ THEN("the norns_task structure is initialized as expected") {
+ REQUIRE(task.t_id == 0);
+ REQUIRE(task.t_op == task_op);
+
+ REQUIRE(task.t_src.r_buffer.b_addr == src_addr);
+
+ REQUIRE(strcmp(task.t_dst.r_posix_path.p_nsid, dst_nsid) == 0);
+ REQUIRE(strcmp(task.t_dst.r_posix_path.p_host, dst_host) == 0);
+ REQUIRE(strcmp(task.t_dst.r_posix_path.p_path, dst_path) == 0);
+ }
+
+ }
+
+ WHEN("initializing a task with src=NORNS_MEMORY_REGION and "
+ "dst=NORNS_LOCAL_PATH") {
+
+ norns_op_t task_op = NORNS_IOTASK_COPY;
+ void* src_addr = (void*) 0xdeadbeef;
+ size_t src_size = (size_t) 42;
+ const char* dst_nsid = "tmp://";
+ const char* dst_path = "/a/b/c";
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(task_op,
+ NORNS_MEMORY_REGION(src_addr, src_size),
+ NORNS_SHARED_PATH(dst_nsid, dst_path));
+
+ THEN("the norns_task structure is initialized as expected") {
+ REQUIRE(task.t_id == 0);
+ REQUIRE(task.t_op == task_op);
+
+ REQUIRE(task.t_src.r_buffer.b_addr == src_addr);
+
+ REQUIRE(strcmp(task.t_dst.r_posix_path.p_nsid, dst_nsid) == 0);
+ REQUIRE(strcmp(task.t_dst.r_posix_path.p_path, dst_path) == 0);
+ }
+ }
+ }
+}
+
diff --git a/tests/api-ctl-task-status.cpp b/tests/api-ctl-task-status.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7dcfe3d17bccf214f82c5e7b64fcca123549a73a
--- /dev/null
+++ b/tests/api-ctl-task-status.cpp
@@ -0,0 +1,1136 @@
+/*************************************************************************
+ * Copyright (C) 2017-2018 Barcelona Supercomputing Center *
+ * Centro Nacional de Supercomputacion *
+ * All rights reserved. *
+ * *
+ * This file is part of the NORNS Data Scheduler, a service that allows *
+ * other programs to start, track and manage asynchronous transfers of *
+ * data resources transfers requests between different storage backends. *
+ * *
+ * See AUTHORS file in the top level directory for information *
+ * regarding developers and contributors. *
+ * *
+ * The NORNS 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 NORNS 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 the NORNS Data Scheduler. If not, see *
+ * . *
+ *************************************************************************/
+
+
+#include "nornsctl.h"
+#include "test-env.hpp"
+#include "catch.hpp"
+
+SCENARIO("check control request", "[api::nornsctl_error]") {
+ GIVEN("a running urd instance") {
+
+ test_env env(
+ fake_daemon_cfg {
+ true /* dry_run? */
+ }
+ );
+
+ const char* nsid0 = "tmp0";
+ const char* nsid1 = "tmp1";
+ bfs::path src_mnt, dst_mnt;
+
+ // create namespaces
+ std::tie(std::ignore, src_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid1, "mnt/tmp1", 16384);
+
+ // define input names
+ std::vector input_data(100, 42);
+ void* src_buf = input_data.data();
+ size_t src_buf_size = input_data.size() * sizeof(int);
+ const bfs::path src_file = "/a/b/c/file";
+ size_t src_file_size = 4096;
+
+ // define output names
+ const bfs::path dst_file = "/b/c/d/file";
+
+ // create input data
+ env.add_to_namespace(nsid0, "/a/b/c/file", 4096);
+
+ /**********************************************************************/
+ /* tests for error conditions */
+ /**********************************************************************/
+
+ WHEN("checking the status of an active request") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(src_buf, src_buf_size),
+ NORNS_LOCAL_PATH(nsid1, dst_file.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ THEN("NORNS_SUCCESS is returned and task status is valid") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE((stats.st_status == NORNS_EPENDING ||
+ stats.st_status == NORNS_EINPROGRESS ||
+ stats.st_status == NORNS_EFINISHED));
+ }
+ }
+ }
+
+ WHEN("checking the status of an active request") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file.c_str()),
+ NORNS_LOCAL_PATH(nsid1, dst_file.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+
+retry:
+ norns_stat_t stats;
+ rv = nornsctl_error(&task, &stats);
+
+ THEN("NORNS_SUCCESS is returned and task status is valid") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE((stats.st_status == NORNS_EPENDING ||
+ stats.st_status == NORNS_EINPROGRESS ||
+ stats.st_status == NORNS_EFINISHED));
+ }
+
+ if(stats.st_status != NORNS_EFINISHED)
+ goto retry;
+ }
+ }
+
+ env.notify_success();
+/*
+ WHEN("submitting a request to copy data using unregistered backends") {
+
+ void* src_addr = (void*) 0xdeadbeef;
+ size_t src_size = (size_t) 42;
+
+ const char* dst_nsid = "tmp://";
+ const char* dst_path = "/a/b/c";
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(src_addr, src_size),
+ NORNS_LOCAL_PATH(dst_nsid, dst_path));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ENOSUCHBACKEND is returned") {
+ REQUIRE(rv == NORNS_ENOSUCHBACKEND);
+ }
+ }
+
+ WHEN("submitting a request to copy data using an unregistered src backend") {
+
+ const char* src_nsid = "tmp://";
+ const char* src_mnt = "/mnt/tmp0";
+ const char* src_path = "/a/b/c";
+
+ const char* dst_nsid = "lustre://";
+ const char* dst_mnt = "/mnt/lustre0";
+ const char* dst_path = "/a/b/c";
+
+ nornsctl_backend_t ns = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_LUSTRE, dst_mnt, 1024);
+
+ norns_error_t rv = nornsctl_register_namespace(&b);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(src_nsid, src_path),
+ NORNS_SHARED_PATH(dst_nsid, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ENOSUCHBACKEND is returned") {
+ REQUIRE(rv == NORNS_ENOSUCHBACKEND);
+ }
+
+ rv = nornsctl_unregister_namespace(dst_nsid);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ WHEN("submitting a request to copy data using an unregistered dst backend") {
+
+ const char* src_nsid = "tmp://";
+ const char* src_mnt = "/mnt/tmp0";
+ const char* src_path = "/a/b/c";
+
+ const char* dst_nsid = "lustre://";
+ const char* dst_mnt = "/mnt/lustre0";
+ const char* dst_path = "/a/b/c";
+
+ nornsctl_backend_t ns = NORNSCTL_BACKEND(src_nsid, NORNS_BACKEND_NVML, src_mnt, 1024);
+ norns_error_t rv = nornsctl_register_namespace(&b);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(src_nsid, src_path),
+ NORNS_SHARED_PATH(dst_nsid, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ENOSUCHBACKEND is returned") {
+ REQUIRE(rv == NORNS_ENOSUCHBACKEND);
+ }
+
+ rv = nornsctl_unregister_namespace(src_nsid);
+
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+*/
+
+
+#if 0
+ /**************************************************************************************************************/
+ /* tests for NORNS_IOTASK_COPY */
+ /**************************************************************************************************************/
+ /* copy from process memory to .* */
+ WHEN("submitting a request to copy from NORNS_PROCESS_MEMORY to NORNS_LOCAL_PATH") {
+
+ const char* src_nsid = "mem://";
+ void* src_addr = (void*) 0xdeadbeef;
+ size_t src_size = (size_t) 42;
+
+ const char* dst_nsid = "tmp://";
+ const char* dst_mnt = "/mnt/tmp0";
+ const char* dst_path = "/a/b/c";
+
+ nornsctl_backend_t bdst = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_POSIX_FILESYSTEM, dst_mnt, 8192);
+ norns_error_t rv = nornsctl_register_namespace(&bdst);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(src_nsid, src_addr, src_size),
+ NORNS_LOCAL_PATH(dst_nsid, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_SUCCESS is returned") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(src_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ WHEN("submitting a request to copy from NORNS_PROCESS_MEMORY to NORNS_SHARED_PATH") {
+
+ const char* src_nsid = "mem://";
+ void* src_addr = (void*) 0xdeadbeef;
+ size_t src_size = (size_t) 42;
+
+ const char* dst_nsid = "tmp://";
+ const char* dst_mnt = "/mnt/tmp0";
+ const char* dst_path = "/a/b/c";
+
+ nornsctl_backend_t bdst = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_LUSTRE, dst_mnt, 8192);
+ norns_error_t rv = nornsctl_register_namespace(&bdst);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(src_nsid, src_addr, src_size),
+ NORNS_SHARED_PATH(dst_nsid, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_SUCCESS is returned") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(src_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ WHEN("submitting a request to copy from NORNS_PROCESS_MEMORY to NORNS_REMOTE_PATH") {
+
+ const char* src_nsid = "mem://";
+ void* src_addr = (void*) 0xdeadbeef;
+ size_t src_size = (size_t) 42;
+
+ const char* dst_nsid = "tmp://";
+ const char* dst_host = "node0";
+ const char* dst_path = "/a/b/c";
+
+ /*
+ nornsctl_backend_t bdst = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_LUSTRE, dst_mnt, 8192);
+ norns_error_t rv = nornsctl_register_namespace(&bdst);
+ REQUIRE(rv == NORNS_SUCCESS);
+ */
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(src_nsid, src_addr, src_size),
+ NORNS_REMOTE_PATH(dst_nsid, dst_host, dst_path));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("NORNS_SUCCESS is returned") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(src_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ /* copy from local path to .* */
+ WHEN("submitting a request to copy from NORNS_LOCAL_PATH to NORNS_LOCAL_PATH") {
+
+ const char* src_nsid = "tmp0://";
+ const char* src_mnt = "/mnt/tmp0";
+ const char* src_path = "/b/c/d";
+
+ const char* dst_nsid = "tmp1://";
+ const char* dst_mnt = "/mnt/tmp1";
+ const char* dst_path = "/a/b/c";
+
+ nornsctl_backend_t bsrc = NORNSCTL_BACKEND(src_nsid, NORNS_BACKEND_NVML, src_mnt, 16384);
+ norns_error_t rv = nornsctl_register_namespace(&bsrc);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ nornsctl_backend_t bdst = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_POSIX_FILESYSTEM, dst_mnt, 8192);
+ rv = nornsctl_register_namespace(&bdst);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(src_nsid, src_path),
+ NORNS_LOCAL_PATH(dst_nsid, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_SUCCESS is returned") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(src_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ WHEN("submitting a request to copy from NORNS_LOCAL_PATH to NORNS_SHARED_PATH") {
+
+ const char* src_nsid = "tmp://";
+ const char* src_mnt = "/mnt/tmp";
+ const char* src_path = "/b/c/d";
+
+ const char* dst_nsid = "lustre://";
+ const char* dst_mnt = "/mnt/lustre";
+ const char* dst_path = "/a/b/c";
+
+ nornsctl_backend_t bsrc = NORNSCTL_BACKEND(src_nsid, NORNS_BACKEND_NVML, src_mnt, 16384);
+ norns_error_t rv = nornsctl_register_namespace(&bsrc);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ nornsctl_backend_t bdst = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_LUSTRE, dst_mnt, 8192);
+ rv = nornsctl_register_namespace(&bdst);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(src_nsid, src_path),
+ NORNS_SHARED_PATH(dst_nsid, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_SUCCESS is returned") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(src_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ WHEN("submitting a request to copy from NORNS_LOCAL_PATH to NORNS_REMOTE_PATH") {
+
+ const char* src_nsid = "tmp://";
+ const char* src_mnt = "/mnt/tmp";
+ const char* src_path = "/b/c/d";
+
+ const char* dst_nsid = "tmp://";
+ const char* dst_mnt = "/mnt/tmp";
+ const char* dst_host = "node1";
+ const char* dst_path = "/a/b/c";
+
+ nornsctl_backend_t bsrc = NORNSCTL_BACKEND(src_nsid, NORNS_BACKEND_NVML, src_mnt, 16384);
+ norns_error_t rv = nornsctl_register_namespace(&bsrc);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ /*
+ nornsctl_backend_t bdst = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_NVML, dst_mnt, 8192);
+ rv = nornsctl_register_namespace(&bdst);
+ REQUIRE(rv == NORNS_SUCCESS);
+ */
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(src_nsid, src_path),
+ NORNS_REMOTE_PATH(dst_nsid, dst_host, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_SUCCESS is returned") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(src_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ /* using a remote node as source is not allowed (yet) */
+ WHEN("submitting a request to copy from NORNS_REMOTE_PATH to NORNS_LOCAL_PATH") {
+
+ const char* src_nsid = "tmp://";
+ const char* src_host = "node0";
+ const char* src_path = "/a/b/c";
+
+ const char* dst_nsid = "tmp://";
+ const char* dst_mnt = "/mnt/tmp";
+ const char* dst_path = "/b/c/d";
+
+ nornsctl_backend_t bdst = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_NVML, dst_mnt, 16384);
+ norns_error_t rv = nornsctl_register_namespace(&bdst);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(src_nsid, src_host, src_path),
+ NORNS_LOCAL_PATH(dst_nsid, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ENOTSUPPORTED is returned") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ /* using a remote node as source is not allowed (yet) */
+ WHEN("submitting a request to copy from NORNS_REMOTE_PATH to NORNS_SHARED_PATH") {
+
+ const char* src_nsid = "tmp://";
+ const char* src_host = "node0";
+ const char* src_path = "/a/b/c";
+
+ const char* dst_nsid = "tmp://";
+ const char* dst_mnt = "/mnt/tmp";
+ const char* dst_path = "/b/c/d";
+
+ nornsctl_backend_t bdst = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_LUSTRE, dst_mnt, 16384);
+ norns_error_t rv = nornsctl_register_namespace(&bdst);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(src_nsid, src_host, src_path),
+ NORNS_SHARED_PATH(dst_nsid, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ENOTSUPPORTED is returned") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ /* using a remote node as source is not allowed (yet) */
+ WHEN("submitting a request to copy from NORNS_REMOTE_PATH to NORNS_REMOTE_PATH") {
+
+ const char* src_nsid = "tmp://";
+ const char* src_host = "node0";
+ const char* src_path = "/a/b/c";
+
+ const char* dst_nsid = "tmp://";
+ const char* dst_host = "node1";
+ const char* dst_path = "/b/c/d";
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(src_nsid, src_host, src_path),
+ NORNS_REMOTE_PATH(dst_nsid, dst_host, dst_path));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ENOTSUPPORTED is returned") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+ }
+
+ /* using the process memory as destination is not allowed (yet) */
+ WHEN("submitting a request to copy from NORNS_LOCAL_PATH to NORNS_PROCESS_MEMORY") {
+
+ const char* src_nsid = "tmp://";
+ const char* src_mnt = "/mnt/tmp";
+ const char* src_path = "/a/b/c";
+
+ const char* dst_nsid = "mem://";
+ void* dst_addr = (void*) 0xdeadbeef;
+ size_t dst_size = (size_t) 42;
+
+
+ nornsctl_backend_t bsrc = NORNSCTL_BACKEND(src_nsid, NORNS_BACKEND_NVML, src_mnt, 16384);
+ norns_error_t rv = nornsctl_register_namespace(&bsrc);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(src_nsid, src_path),
+ NORNS_MEMORY_REGION(dst_nsid, dst_addr, dst_size));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ENOTSUPPORTED is returned") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(src_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ /* using the process memory as destination is not allowed (yet) */
+ WHEN("submitting a request to copy from NORNS_SHARED_PATH to NORNS_PROCESS_MEMORY") {
+
+ const char* src_nsid = "lustre://";
+ const char* src_mnt = "/mnt/lustre";
+ const char* src_path = "/a/b/c";
+
+ const char* dst_nsid = "mem://";
+ void* dst_addr = (void*) 0xdeadbeef;
+ size_t dst_size = (size_t) 42;
+
+
+ nornsctl_backend_t bsrc = NORNSCTL_BACKEND(src_nsid, NORNS_BACKEND_LUSTRE, src_mnt, 16384);
+ norns_error_t rv = nornsctl_register_namespace(&bsrc);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_SHARED_PATH(src_nsid, src_path),
+ NORNS_MEMORY_REGION(dst_nsid, dst_addr, dst_size));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ENOTSUPPORTED is returned") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(src_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ /* using the process memory as destination is not allowed (yet) */
+ WHEN("submitting a request to copy from NORNS_REMOTE_PATH to NORNS_PROCESS_MEMORY") {
+
+ const char* src_nsid = "tmp://";
+ const char* src_host = "node0";
+ const char* src_path = "/a/b/c";
+
+ const char* dst_nsid = "mem://";
+ void* dst_addr = (void*) 0xdeadbeef;
+ size_t dst_size = (size_t) 42;
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(src_nsid, src_host, src_path),
+ NORNS_MEMORY_REGION(dst_nsid, dst_addr, dst_size));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ENOTSUPPORTED is returned") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+
+ /**************************************************************************************************************/
+ /* tests for NORNS_IOTASK_MOVE */
+ /**************************************************************************************************************/
+ /* move from process memory to .* */
+ WHEN("submitting a request to move from NORNS_PROCESS_MEMORY to NORNS_LOCAL_PATH") {
+
+ const char* src_nsid = "mem://";
+ void* src_addr = (void*) 0xdeadbeef;
+ size_t src_size = (size_t) 42;
+
+ const char* dst_nsid = "tmp://";
+ const char* dst_mnt = "/mnt/tmp0";
+ const char* dst_path = "/a/b/c";
+
+ nornsctl_backend_t bdst = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_POSIX_FILESYSTEM, dst_mnt, 8192);
+ norns_error_t rv = nornsctl_register_namespace(&bdst);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_MEMORY_REGION(src_nsid, src_addr, src_size),
+ NORNS_LOCAL_PATH(dst_nsid, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_SUCCESS is returned") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(src_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ WHEN("submitting a request to move from NORNS_PROCESS_MEMORY to NORNS_SHARED_PATH") {
+
+ const char* src_nsid = "mem://";
+ void* src_addr = (void*) 0xdeadbeef;
+ size_t src_size = (size_t) 42;
+
+ const char* dst_nsid = "tmp://";
+ const char* dst_mnt = "/mnt/tmp0";
+ const char* dst_path = "/a/b/c";
+
+ nornsctl_backend_t bdst = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_LUSTRE, dst_mnt, 8192);
+ rv = nornsctl_register_namespace(&bdst);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_MEMORY_REGION(src_nsid, src_addr, src_size),
+ NORNS_SHARED_PATH(dst_nsid, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_SUCCESS is returned") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(src_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ WHEN("submitting a request to move from NORNS_PROCESS_MEMORY to NORNS_REMOTE_PATH") {
+
+ const char* src_nsid = "mem://";
+ void* src_addr = (void*) 0xdeadbeef;
+ size_t src_size = (size_t) 42;
+
+ const char* dst_nsid = "tmp://";
+ const char* dst_host = "node0";
+ const char* dst_path = "/a/b/c";
+
+ /*
+ nornsctl_backend_t bdst = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_LUSTRE, dst_mnt, 8192);
+ rv = nornsctl_register_namespace(&bdst);
+ REQUIRE(rv == NORNS_SUCCESS);
+ */
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_MEMORY_REGION(src_nsid, src_addr, src_size),
+ NORNS_REMOTE_PATH(dst_nsid, dst_host, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_SUCCESS is returned") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(src_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ /* move from local path to .* */
+ WHEN("submitting a request to move from NORNS_LOCAL_PATH to NORNS_LOCAL_PATH") {
+
+ const char* src_nsid = "tmp0://";
+ const char* src_mnt = "/mnt/tmp0";
+ const char* src_path = "/b/c/d";
+
+ const char* dst_nsid = "tmp1://";
+ const char* dst_mnt = "/mnt/tmp1";
+ const char* dst_path = "/a/b/c";
+
+ nornsctl_backend_t bsrc = NORNSCTL_BACKEND(src_nsid, NORNS_BACKEND_NVML, src_mnt, 16384);
+ norns_error_t rv = nornsctl_register_namespace(&bsrc);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ nornsctl_backend_t bdst = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_POSIX_FILESYSTEM, dst_mnt, 8192);
+ rv = nornsctl_register_namespace(&bdst);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_LOCAL_PATH(src_nsid, src_path),
+ NORNS_LOCAL_PATH(dst_nsid, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_SUCCESS is returned") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(src_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ WHEN("submitting a request to move from NORNS_LOCAL_PATH to NORNS_SHARED_PATH") {
+
+ const char* src_nsid = "tmp://";
+ const char* src_mnt = "/mnt/tmp";
+ const char* src_path = "/b/c/d";
+
+ const char* dst_nsid = "lustre://";
+ const char* dst_mnt = "/mnt/lustre";
+ const char* dst_path = "/a/b/c";
+
+ nornsctl_backend_t bsrc = NORNSCTL_BACKEND(src_nsid, NORNS_BACKEND_NVML, src_mnt, 16384);
+ norns_error_t rv = nornsctl_register_namespace(&bsrc);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ nornsctl_backend_t bdst = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_LUSTRE, dst_mnt, 8192);
+ rv = nornsctl_register_namespace(&bdst);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_LOCAL_PATH(src_nsid, src_path),
+ NORNS_SHARED_PATH(dst_nsid, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_SUCCESS is returned") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(src_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ WHEN("submitting a request to move from NORNS_LOCAL_PATH to NORNS_REMOTE_PATH") {
+
+ const char* src_nsid = "tmp://";
+ const char* src_mnt = "/mnt/tmp";
+ const char* src_path = "/b/c/d";
+
+ const char* dst_nsid = "tmp://";
+ const char* dst_mnt = "/mnt/tmp";
+ const char* dst_host = "node1";
+ const char* dst_path = "/a/b/c";
+
+ nornsctl_backend_t bsrc = NORNSCTL_BACKEND(src_nsid, NORNS_BACKEND_NVML, src_mnt, 16384);
+ norns_error_t rv = nornsctl_register_namespace(&bsrc);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ /*
+ nornsctl_backend_t bdst = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_NVML, dst_mnt, 8192);
+ rv = nornsctl_register_namespace(&bdst);
+ REQUIRE(rv == NORNS_SUCCESS);
+ */
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_LOCAL_PATH(src_nsid, src_path),
+ NORNS_REMOTE_PATH(dst_nsid, dst_host, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_SUCCESS is returned") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(src_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ /* using a remote node as source is not allowed (yet) */
+ WHEN("submitting a request to move from NORNS_REMOTE_PATH to NORNS_LOCAL_PATH") {
+
+ const char* src_nsid = "tmp://";
+ const char* src_host = "node0";
+ const char* src_path = "/a/b/c";
+
+ const char* dst_nsid = "tmp://";
+ const char* dst_mnt = "/mnt/tmp";
+ const char* dst_path = "/b/c/d";
+
+ nornsctl_backend_t bdst = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_NVML, dst_mnt, 16384);
+ norns_error_t rv = nornsctl_register_namespace(&bdst);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_REMOTE_PATH(src_nsid, src_host, src_path),
+ NORNS_LOCAL_PATH(dst_nsid, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ENOTSUPPORTED is returned") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ /* using a remote node as source is not allowed (yet) */
+ WHEN("submitting a request to move from NORNS_REMOTE_PATH to NORNS_SHARED_PATH") {
+
+ const char* src_nsid = "tmp://";
+ const char* src_host = "node0";
+ const char* src_path = "/a/b/c";
+
+ const char* dst_nsid = "tmp://";
+ const char* dst_mnt = "/mnt/tmp";
+ const char* dst_path = "/b/c/d";
+
+ nornsctl_backend_t bdst = NORNSCTL_BACKEND(dst_nsid, NORNS_BACKEND_LUSTRE, dst_mnt, 16384);
+ norns_error_t rv = nornsctl_register_namespace(&bdst);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_REMOTE_PATH(src_nsid, src_host, src_path),
+ NORNS_SHARED_PATH(dst_nsid, dst_path));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ENOTSUPPORTED is returned") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ /* using a remote node as source is not allowed (yet) */
+ WHEN("submitting a request to move from NORNS_REMOTE_PATH to NORNS_REMOTE_PATH") {
+
+ const char* src_nsid = "tmp://";
+ const char* src_host = "node0";
+ const char* src_path = "/a/b/c";
+
+ const char* dst_nsid = "tmp://";
+ const char* dst_host = "node1";
+ const char* dst_path = "/b/c/d";
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_REMOTE_PATH(src_nsid, src_host, src_path),
+ NORNS_REMOTE_PATH(dst_nsid, dst_host, dst_path));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ENOTSUPPORTED is returned") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+ }
+
+ /* using the process memory as destination is not allowed (yet) */
+ WHEN("submitting a request to move from NORNS_LOCAL_PATH to NORNS_PROCESS_MEMORY") {
+
+ const char* src_nsid = "tmp://";
+ const char* src_mnt = "/mnt/tmp";
+ const char* src_path = "/a/b/c";
+
+ const char* dst_nsid = "mem://";
+ void* dst_addr = (void*) 0xdeadbeef;
+ size_t dst_size = (size_t) 42;
+
+
+ nornsctl_backend_t bsrc = NORNSCTL_BACKEND(src_nsid, NORNS_BACKEND_NVML, src_mnt, 16384);
+ norns_error_t rv = nornsctl_register_namespace(&bsrc);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_LOCAL_PATH(src_nsid, src_path),
+ NORNS_MEMORY_REGION(dst_nsid, dst_addr, dst_size));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ENOTSUPPORTED is returned") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(src_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ /* using the process memory as destination is not allowed (yet) */
+ WHEN("submitting a request to move from NORNS_SHARED_PATH to NORNS_PROCESS_MEMORY") {
+
+ const char* src_nsid = "lustre://";
+ const char* src_mnt = "/mnt/lustre";
+ const char* src_path = "/a/b/c";
+
+ const char* dst_nsid = "mem://";
+ void* dst_addr = (void*) 0xdeadbeef;
+ size_t dst_size = (size_t) 42;
+
+
+ nornsctl_backend_t bsrc = NORNSCTL_BACKEND(src_nsid, NORNS_BACKEND_LUSTRE, src_mnt, 16384);
+ norns_error_t rv = nornsctl_register_namespace(&bsrc);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_SHARED_PATH(src_nsid, src_path),
+ NORNS_MEMORY_REGION(dst_nsid, dst_addr, dst_size));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ENOTSUPPORTED is returned") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+
+ // cleanup
+ rv = nornsctl_unregister_namespace(src_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+
+ /* using the process memory as destination is not allowed (yet) */
+ WHEN("submitting a request to move from NORNS_REMOTE_PATH to NORNS_PROCESS_MEMORY") {
+
+ const char* src_nsid = "tmp://";
+ const char* src_host = "node0";
+ const char* src_path = "/a/b/c";
+
+ const char* dst_nsid = "mem://";
+ void* dst_addr = (void*) 0xdeadbeef;
+ size_t dst_size = (size_t) 42;
+
+ norns_iotask_t task = NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_REMOTE_PATH(src_nsid, src_host, src_path),
+ NORNS_MEMORY_REGION(dst_nsid, dst_addr, dst_size));
+
+ rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ENOTSUPPORTED is returned") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+
+ rv = nornsctl_unregister_namespace(dst_nsid);
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+#endif
+
+ env.notify_success();
+ }
+
+#ifndef USE_REAL_DAEMON
+ GIVEN("a non-running urd instance") {
+ WHEN("attempting to request a transfer") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(
+ NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH("nvml0://", "/a/b/c/"),
+ NORNS_REMOTE_PATH("nvml0://", "node1", "/a/b/d/"));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("NORNS_ECONNFAILED is returned") {
+ REQUIRE(rv == NORNS_ECONNFAILED);
+ }
+ }
+ }
+#endif
+}
+
+
+SCENARIO("check requests", "[api::nornsctl_status]") {
+ GIVEN("a running urd instance") {
+
+ test_env env(
+ fake_daemon_cfg {
+ true /* dry_run? */
+ }
+ );
+
+ const char* nsid0 = "tmp0";
+ const char* nsid1 = "tmp1";
+ bfs::path src_mnt, dst_mnt;
+
+ // create namespaces
+ std::tie(std::ignore, src_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid1, "mnt/tmp1", 16384);
+
+ // define input names
+ void* src_buf;
+ size_t src_buf_size __attribute__((unused));
+ const bfs::path src_file = "/a/b/c/file";
+ size_t src_file_size = 4096;
+
+ // define output names
+ const bfs::path dst_file = "/b/c/d/file";
+
+ // create input data
+ env.add_to_namespace(nsid0, src_file, 4096);
+
+ // 64MiB buffer
+ std::vector input_data(16*1024*1024, 42);
+ src_buf = input_data.data();
+ src_buf_size = input_data.size() * sizeof(int);
+
+ WHEN("checking the status of all requests without actual requests running") {
+ nornsctl_stat_t global_stats;
+ norns_error_t rv = nornsctl_status(&global_stats);
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(global_stats.st_pending_tasks == 0);
+ REQUIRE(global_stats.st_running_tasks == 0);
+ REQUIRE(global_stats.st_eta == 0.0);
+ }
+
+ WHEN("checking the status of all requests") {
+
+ const size_t ntasks = 10;
+ norns_iotask_t tasks[ntasks];
+ size_t sizes[] =
+ { 4*1024*1024, 16*1024*1024, 32*1024*1024, 64*1024*1024 };
+
+ for(size_t i=0; i. *
+ *************************************************************************/
+
+#include "norns.h"
+#include "test-env.hpp"
+#include "catch.hpp"
+
+SCENARIO("submit control request", "[api::nornsctl_submit]") {
+ GIVEN("a running urd instance") {
+
+ test_env env(
+ fake_daemon_cfg {
+ true /* dry_run? */
+ }
+ );
+
+ const char* nsid0 = "tmp0";
+ const char* nsid1 = "tmp1";
+ const char* nsid3 = "lustre0";
+ bfs::path tmp0_mnt, tmp1_mnt, lustre_mnt;
+
+ // create namespaces
+ std::tie(std::ignore, tmp0_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, tmp1_mnt) =
+ env.create_namespace(nsid1, "mnt/tmp1", 16384);
+ std::tie(std::ignore, lustre_mnt) =
+ env.create_namespace(nsid3, "mnt/lustre0", 16384);
+
+ // define input names
+ const char* src_host0 = "node0";
+ const bfs::path src_file0 = "/a/b/c";
+ const bfs::path src_file1 = "/b/c/d";
+ void* src_mem_addr = (void*) 0xdeadbeef;
+ const size_t src_mem_size = (size_t) 42;
+
+ // define output names
+ const char* dst_host0 = "node0";
+ const bfs::path dst_file0 = "/a/b/c";
+ const bfs::path dst_file1 = "/b/c/d";
+ void* dst_mem_addr = (void*) 0xdeadbeef;
+ const size_t dst_mem_size = (size_t) 42;
+
+ /**********************************************************************/
+ /* tests for error conditions */
+ /**********************************************************************/
+ WHEN("submitting a request to copy data using unregistered "
+ "namespaces") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(src_mem_addr, src_mem_size),
+ NORNS_LOCAL_PATH("tmp2", dst_file0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_ENOSUCHNAMESPACE") {
+ REQUIRE(rv == NORNS_ENOSUCHNAMESPACE);
+ }
+ }
+
+ WHEN("submitting a request to copy data using an unregistered src "
+ "namespace") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH("tmp2", src_file0.c_str()),
+ NORNS_SHARED_PATH(nsid3, dst_file0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_ENOSUCHNAMESPACE") {
+ REQUIRE(rv == NORNS_ENOSUCHNAMESPACE);
+ }
+ }
+
+ WHEN("submitting a request to copy data using an unregistered dst "
+ "namespace") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file0.c_str()),
+ NORNS_SHARED_PATH("tmp2", dst_file0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_ENOSUCHNAMESPACE") {
+ REQUIRE(rv == NORNS_ENOSUCHNAMESPACE);
+ }
+ }
+
+
+ /**********************************************************************/
+ /* tests for NORNS_IOTASK_COPY */
+ /**********************************************************************/
+ /* copy from process memory to .* */
+ WHEN("submitting a request to copy from NORNS_MEMORY_REGION to "
+ "NORNS_LOCAL_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(src_mem_addr, src_mem_size),
+ NORNS_LOCAL_PATH(nsid0, dst_file0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+ }
+
+ WHEN("submitting a request to copy from NORNS_MEMORY_REGION to "
+ "NORNS_SHARED_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(src_mem_addr, src_mem_size),
+ NORNS_SHARED_PATH(nsid0, dst_file0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+ }
+
+ WHEN("submitting a request to copy from a NORNS_MEMORY_REGION to "
+ "a NORNS_REMOTE_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(src_mem_addr, src_mem_size),
+ NORNS_REMOTE_PATH(nsid0,
+ dst_host0,
+ dst_file0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+ }
+
+ /* copy from local path to .* */
+ WHEN("submitting a request to copy from NORNS_LOCAL_PATH to "
+ "NORNS_LOCAL_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file1.c_str()),
+ NORNS_LOCAL_PATH(nsid1, dst_file0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+ }
+
+ WHEN("submitting a request to copy from NORNS_LOCAL_PATH to "
+ "NORNS_SHARED_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file1.c_str()),
+ NORNS_SHARED_PATH(nsid3, dst_file0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+ }
+
+ WHEN("submitting a request to copy from NORNS_LOCAL_PATH to "
+ "NORNS_REMOTE_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file1.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ dst_host0,
+ dst_file0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+ }
+
+ /* using a remote node as source is not allowed (yet) */
+ WHEN("submitting a request to copy from NORNS_REMOTE_PATH to "
+ "NORNS_LOCAL_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ src_host0,
+ src_file0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() return NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+ }
+
+ /* using a remote node as source is not allowed (yet) */
+ WHEN("submitting a request to copy from NORNS_REMOTE_PATH to "
+ "NORNS_SHARED_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ src_host0,
+ src_file0.c_str()),
+ NORNS_SHARED_PATH(nsid1, dst_file1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_ENOTSUPPORTED") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+ }
+
+ /* using a remote node as source is not allowed (yet) */
+ WHEN("submitting a request to copy from NORNS_REMOTE_PATH to "
+ "NORNS_REMOTE_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ src_host0,
+ src_file0.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ dst_host0,
+ dst_file1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_ENOTSUPPORTED") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+ }
+
+ /* using the process memory as destination is not allowed (yet) */
+ WHEN("submitting a request to copy from NORNS_LOCAL_PATH to "
+ "NORNS_MEMORY_REGION") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file0.c_str()),
+ NORNS_MEMORY_REGION(dst_mem_addr,
+ dst_mem_size));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_ENOTSUPPORTED") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+ }
+
+ /* using the process memory as destination is not allowed (yet) */
+ WHEN("submitting a request to copy from NORNS_SHARED_PATH to "
+ "NORNS_MEMORY_REGION") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_SHARED_PATH(nsid3, src_file0.c_str()),
+ NORNS_MEMORY_REGION(dst_mem_addr,
+ dst_mem_size));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_ENOTSUPPORTED") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+ }
+
+ /* using the process memory as destination is not allowed (yet) */
+ WHEN("submitting a request to copy from NORNS_REMOTE_PATH to "
+ "NORNS_MEMORY_REGION") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_REMOTE_PATH(nsid0,
+ src_host0,
+ src_file0.c_str()),
+ NORNS_MEMORY_REGION(dst_mem_addr,
+ dst_mem_size));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_ENOTSUPPORTED") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+ }
+
+
+ /**********************************************************************/
+ /* tests for NORNS_IOTASK_MOVE */
+ /**********************************************************************/
+ /* move from process memory to .* */
+ WHEN("submitting a request to move from NORNS_MEMORY_REGION to "
+ "NORNS_LOCAL_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_MEMORY_REGION(src_mem_addr, src_mem_size),
+ NORNS_LOCAL_PATH(nsid1, dst_file0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+ }
+
+ WHEN("submitting a request to move from NORNS_MEMORY_REGION to "
+ "NORNS_SHARED_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_MEMORY_REGION(src_mem_addr, src_mem_size),
+ NORNS_SHARED_PATH(nsid1, dst_file0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+ }
+
+ WHEN("submitting a request to move from NORNS_MEMORY_REGION to "
+ "NORNS_REMOTE_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_MEMORY_REGION(src_mem_addr, src_mem_size),
+ NORNS_REMOTE_PATH(nsid1,
+ dst_host0,
+ dst_file0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+ }
+
+ /* move from local path to .* */
+ WHEN("submitting a request to move from NORNS_LOCAL_PATH to "
+ "NORNS_LOCAL_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_LOCAL_PATH(nsid0, src_file1.c_str()),
+ NORNS_LOCAL_PATH(nsid1, dst_file0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+ }
+
+ WHEN("submitting a request to move from NORNS_LOCAL_PATH to "
+ "NORNS_SHARED_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_LOCAL_PATH(nsid0, src_file1.c_str()),
+ NORNS_SHARED_PATH(nsid3, dst_file0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+ }
+
+ WHEN("submitting a request to move from NORNS_LOCAL_PATH to "
+ "NORNS_REMOTE_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_LOCAL_PATH(nsid0, src_file1.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ dst_host0,
+ dst_file0.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ REQUIRE(task.t_id != 0);
+ }
+ }
+
+ /* using a remote node as source is not allowed (yet) */
+ WHEN("submitting a request to move from NORNS_REMOTE_PATH to "
+ "NORNS_LOCAL_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_REMOTE_PATH(nsid0,
+ src_host0,
+ src_file0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_SUCCESS") {
+ REQUIRE(rv == NORNS_SUCCESS);
+ }
+ }
+
+ /* using a remote node as source is not allowed (yet) */
+ WHEN("submitting a request to move from NORNS_REMOTE_PATH to "
+ "NORNS_SHARED_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_REMOTE_PATH(nsid0,
+ src_host0,
+ src_file0.c_str()),
+ NORNS_SHARED_PATH(nsid1, dst_file1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_ENOTSUPPORTED") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+ }
+
+ /* using a remote node as source is not allowed (yet) */
+ WHEN("submitting a request to move from NORNS_REMOTE_PATH to "
+ "NORNS_REMOTE_PATH") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_REMOTE_PATH(nsid0,
+ src_host0,
+ src_file0.c_str()),
+ NORNS_REMOTE_PATH(nsid1,
+ dst_host0,
+ dst_file1.c_str()));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_ENOTSUPPORTED") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+ }
+
+ /* using the process memory as destination is not allowed (yet) */
+ WHEN("submitting a request to move from NORNS_LOCAL_PATH to "
+ "NORNS_MEMORY_REGION") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_LOCAL_PATH(nsid0, src_file0.c_str()),
+ NORNS_MEMORY_REGION(dst_mem_addr,
+ dst_mem_size));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_ENOTSUPPORTED") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+ }
+
+ /* using the process memory as destination is not allowed (yet) */
+ WHEN("submitting a request to move from NORNS_SHARED_PATH to "
+ "NORNS_MEMORY_REGION") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_SHARED_PATH(nsid3, src_file0.c_str()),
+ NORNS_MEMORY_REGION(dst_mem_addr, dst_mem_size));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_ENOTSUPPORTED") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+ }
+
+ /* using the process memory as destination is not allowed (yet) */
+ WHEN("submitting a request to move from NORNS_REMOTE_PATH to "
+ "NORNS_MEMORY_REGION") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_MOVE,
+ NORNS_REMOTE_PATH(nsid0,
+ src_host0,
+ src_file0.c_str()),
+ NORNS_MEMORY_REGION(dst_mem_addr,
+ dst_mem_size));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_ENOTSUPPORTED") {
+ REQUIRE(rv == NORNS_ENOTSUPPORTED);
+ }
+ }
+
+ env.notify_success();
+ }
+
+#ifndef USE_REAL_DAEMON
+ GIVEN("a non-running urd instance") {
+ WHEN("attempting to request a transfer") {
+
+ norns_iotask_t task =
+ NORNSCTL_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH("nvml0://", "/a/b/c/"),
+ NORNS_REMOTE_PATH("nvml0://",
+ "node1",
+ "/a/b/d/"));
+
+ norns_error_t rv = nornsctl_submit(&task);
+
+ THEN("nornsctl_submit() returns NORNS_ECONNFAILED") {
+ REQUIRE(rv == NORNS_ECONNFAILED);
+ }
+ }
+ }
+#endif
+}
diff --git a/tests/api-remove-local-data.cpp b/tests/api-remove-local-data.cpp
index 907d945dd36ee1dd3f8230a6e67edf0f5db4d8e5..2a3bd3c680f449e05ed72d474d5570bc67ceeb34 100644
--- a/tests/api-remove-local-data.cpp
+++ b/tests/api-remove-local-data.cpp
@@ -26,14 +26,14 @@
*************************************************************************/
#include "norns.h"
-#include "nornsctl.h"
#include "test-env.hpp"
#include "compare-files.hpp"
#include "catch.hpp"
namespace bfs = boost::filesystem;
-SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_files]") {
+SCENARIO("remove a local POSIX file",
+ "[api::norns_submit_remove_local_posix_files]") {
GIVEN("a running urd instance") {
test_env env;
@@ -43,8 +43,10 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
bfs::path src_mnt, dst_mnt;
// create namespaces
- std::tie(std::ignore, src_mnt) = env.create_namespace(nsid0, "mnt/tmp0", 16384);
- std::tie(std::ignore, dst_mnt) = env.create_namespace(nsid1, "mnt/tmp1", 16384);
+ std::tie(std::ignore, src_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid1, "mnt/tmp1", 16384);
// define input names
const bfs::path src_file_at_root = "/file0";
@@ -134,30 +136,32 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
// create required output directories
env.add_to_namespace(nsid1, dst_subdir1);
- /**************************************************************************************************************/
- /* tests for error conditions */
- /**************************************************************************************************************/
+ /**********************************************************************/
+ /* tests for error conditions */
+ /**********************************************************************/
// - trying to remove a non-existing file
WHEN("removing a non-existing NORNS_LOCAL_PATH file") {
- norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_REMOVE,
- NORNS_LOCAL_PATH(nsid0, src_invalid_file.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0, src_invalid_file.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "ENOENT") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -172,24 +176,26 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
// - trying to remove a non-existing directory
WHEN("removing a non-existing NORNS_LOCAL_PATH directory") {
- norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_REMOVE,
- NORNS_LOCAL_PATH(nsid0, src_invalid_dir.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0, src_invalid_dir.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and ENOENT are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "ENOENT") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -204,29 +210,32 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
#ifdef __SETCAP_TESTS__
// - trying to copy a file from namespace root with invalid access permissions
- WHEN("copying a NORNS_LOCAL_PATH file from \"/\" without appropriate permissions to access it") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying a NORNS_LOCAL_PATH file from \"/\" without appropriate "
+ "permissions to access it") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_noperms_file0.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_file0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -240,29 +249,31 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
}
// - trying to copy a file from namespace root with invalid access permissions
- WHEN("copying a NORNS_LOCAL_PATH file from a subdir without appropriate permissions to access it") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying a NORNS_LOCAL_PATH file from a subdir without "
+ "appropriate permissions to access it") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_noperms_file1.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_noperms_file1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -276,29 +287,31 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
}
// - trying to copy a file from namespace root with invalid access permissions
- WHEN("copying a NORNS_LOCAL_PATH file from a subdir without appropriate permissions to access a parent") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying a NORNS_LOCAL_PATH file from a subdir without "
+ "appropriate permissions to access a parent") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_noperms_file2.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_noperms_file2.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -312,29 +325,32 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
}
// - trying to copy a subdir from namespace root with invalid access permissions
- WHEN("copying a NORNS_LOCAL_PATH subdir from \"/\" without appropriate permissions to access it") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying a NORNS_LOCAL_PATH subdir from \"/\" without "
+ "appropriate permissions to access it") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_noperms_subdir0.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir0.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -348,29 +364,32 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
}
// - trying to copy a subdir from namespace root with invalid access permissions
- WHEN("copying a NORNS_LOCAL_PATH subdir from another subdir without appropriate permissions to access it") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying a NORNS_LOCAL_PATH subdir from another subdir without "
+ "appropriate permissions to access it") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_noperms_subdir1.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir1.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -384,29 +403,32 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
}
// - trying to copy a subdir from namespace root with invalid access permissions
- WHEN("copying a NORNS_LOCAL_PATH subdir from another subdir without appropriate permissions to access a parent") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
+ WHEN("copying a NORNS_LOCAL_PATH subdir from another subdir without "
+ "appropriate permissions to access a parent") {
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_noperms_subdir2.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file_at_root0.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0,
+ src_noperms_subdir2.c_str()),
+ NORNS_LOCAL_PATH(nsid1,
+ dst_file_at_root0.c_str()));
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("NORNS_ESYSTEMERROR and EACCES|EPERM|EINVAL are reported") {
+ THEN("norns_error() reports NORNS_ESYSTEMERROR and "
+ "EACCES|EPERM|EINVAL") {
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(stats.st_status == NORNS_EFINISHEDWERROR);
@@ -420,26 +442,27 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
}
#endif
- /**************************************************************************************************************/
- /* tests for single files */
- /**************************************************************************************************************/
+ /**********************************************************************/
+ /* tests for single files */
+ /**********************************************************************/
// rm ns0://file0.txt
WHEN("removing a single NORNS_LOCAL_PATH from src namespace's root") {
- norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_REMOVE,
- NORNS_LOCAL_PATH(nsid0, src_file_at_root.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0, src_file_at_root.c_str()));
const bfs::path p = env.get_from_namespace(nsid0, src_file_at_root);
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("File no longer exists") {
@@ -450,22 +473,26 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
}
// rm ns0://a/b/c/.../d/file0.txt
- WHEN("removing a single NORNS_LOCAL_PATH from a src namespace's subdir") {
+ WHEN("removing a single NORNS_LOCAL_PATH from a src namespace's "
+ "subdir") {
- norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_REMOVE,
- NORNS_LOCAL_PATH(nsid0, src_file_at_subdir.c_str()));
- const bfs::path p = env.get_from_namespace(nsid0, src_file_at_subdir);
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0,
+ src_file_at_subdir.c_str()));
+ const bfs::path p =
+ env.get_from_namespace(nsid0, src_file_at_subdir);
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("File no longer exists") {
@@ -475,26 +502,28 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
}
}
- /**************************************************************************************************************/
- /* tests for directories */
- /**************************************************************************************************************/
+ /**********************************************************************/
+ /* tests for directories */
+ /**********************************************************************/
// rm -r /a/contents.*
- WHEN("removing the contents of a NORNS_LOCAL_PATH subdir from src namespace's root") {
-
- norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_REMOVE,
- NORNS_LOCAL_PATH(nsid0, src_subdir0.c_str()));
+ WHEN("removing the contents of a NORNS_LOCAL_PATH subdir from src "
+ "namespace's root") {
+
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0, src_subdir0.c_str()));
const bfs::path p = env.get_from_namespace(nsid0, src_subdir0);
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Directory no longer exists") {
@@ -505,22 +534,23 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
}
// rm -r /a/b/c/.../contents.*
- WHEN("removing the contents of a NORNS_LOCAL_PATH arbitrary subdir to") {
+ WHEN("removing the contents of a NORNS_LOCAL_PATH arbitrary subdir") {
- norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_REMOVE,
- NORNS_LOCAL_PATH(nsid0, src_subdir1.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0, src_subdir1.c_str()));
const bfs::path p = env.get_from_namespace(nsid0, src_subdir1);
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Directory no longer exists") {
@@ -532,20 +562,21 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
WHEN("removing an empty NORNS_LOCAL_PATH directory") {
- norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_REMOVE,
- NORNS_LOCAL_PATH(nsid0, src_empty_dir.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0, src_empty_dir.c_str()));
const bfs::path p = env.get_from_namespace(nsid0, src_empty_dir);
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
THEN("Directory no longer exists") {
@@ -556,31 +587,36 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
}
- /**************************************************************************************************************/
- /* tests for soft links */
- /**************************************************************************************************************/
+ /**********************************************************************/
+ /* tests for soft links */
+ /**********************************************************************/
WHEN("removing a single NORNS_LOCAL_PATH file from src namespace's '/' "
"through a symlink also located at '/'" ) {
- norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_REMOVE,
- NORNS_LOCAL_PATH(nsid0, src_symlink_at_root0.c_str()));
- const bfs::path p = env.get_from_namespace(nsid0, "/") / src_symlink_at_root0;
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_root0.c_str()));
+ const bfs::path p =
+ env.get_from_namespace(nsid0, "/") / src_symlink_at_root0;
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("symlink no longer exists and original file is left intact") {
+ THEN("symlink no longer exists and original file is left "
+ "intact") {
REQUIRE(!bfs::exists(p));
- REQUIRE(bfs::exists(env.get_from_namespace(nsid0, src_file_at_root)));
+ REQUIRE(bfs::exists(
+ env.get_from_namespace(nsid0, src_file_at_root)));
}
}
}
@@ -589,25 +625,30 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
WHEN("removing a single NORNS_LOCAL_PATH arbitrary subdir"
"through a symlink located at '/'" ) {
- norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_REMOVE,
- NORNS_LOCAL_PATH(nsid0, src_symlink_at_root2.c_str()));
- const bfs::path p = env.get_from_namespace(nsid0, "/") / src_symlink_at_root2;
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_root2.c_str()));
+ const bfs::path p =
+ env.get_from_namespace(nsid0, "/") / src_symlink_at_root2;
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("symlink no longer exists and original file is left intact") {
+ THEN("symlink no longer exists and original file is left "
+ "intact") {
REQUIRE(!bfs::exists(p));
- REQUIRE(bfs::exists(env.get_from_namespace(nsid0, src_subdir1)));
+ REQUIRE(bfs::exists(
+ env.get_from_namespace(nsid0, src_subdir1)));
}
}
}
@@ -616,50 +657,59 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
WHEN("removing a single NORNS_LOCAL_PATH file from src namespace's '/' "
"through a symlink located in a subdir" ) {
- norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_REMOVE,
- NORNS_LOCAL_PATH(nsid0, src_symlink_at_subdir0.c_str()));
- const bfs::path p = env.get_from_namespace(nsid0, "/") / src_symlink_at_subdir0;
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_subdir0.c_str()));
+ const bfs::path p =
+ env.get_from_namespace(nsid0, "/") / src_symlink_at_subdir0;
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("symlink no longer exists and original file is left intact") {
+ THEN("symlink no longer exists and original file is left "
+ "intact") {
REQUIRE(!bfs::exists(p));
- REQUIRE(bfs::exists(env.get_from_namespace(nsid0, src_file_at_root)));
+ REQUIRE(bfs::exists(
+ env.get_from_namespace(nsid0, src_file_at_root)));
}
}
}
}
- WHEN("removing a single NORNS_LOCAL_PATH subdir from src namespace's '/' "
- "through a symlink also located at subdir" ) {
+ WHEN("removing a single NORNS_LOCAL_PATH subdir from src namespace's "
+ "'/' through a symlink also located at subdir") {
- norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_REMOVE,
- NORNS_LOCAL_PATH(nsid0, src_symlink_at_subdir1.c_str()));
- const bfs::path p = env.get_from_namespace(nsid0, "/") / src_symlink_at_subdir1;
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_subdir1.c_str()));
+ const bfs::path p =
+ env.get_from_namespace(nsid0, "/") / src_symlink_at_subdir1;
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("symlink no longer exists and original file is left intact") {
+ THEN("symlink no longer exists and original file is left "
+ "intact") {
REQUIRE(!bfs::exists(p));
REQUIRE(bfs::exists(env.get_from_namespace(nsid0, src_subdir0)));
}
@@ -670,25 +720,30 @@ SCENARIO("remove a local POSIX file", "[api::norns_submit_remove_local_posix_fil
WHEN("removing a single NORNS_LOCAL_PATH arbitrary subdir"
"through a symlink also located at a subdir" ) {
- norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_REMOVE,
- NORNS_LOCAL_PATH(nsid0, src_symlink_at_subdir2.c_str()));
- const bfs::path p = env.get_from_namespace(nsid0, "/") / src_symlink_at_subdir2;
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_REMOVE,
+ NORNS_LOCAL_PATH(nsid0,
+ src_symlink_at_subdir2.c_str()));
+ const bfs::path p =
+ env.get_from_namespace(nsid0, "/") / src_symlink_at_subdir2;
norns_error_t rv = norns_submit(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_submit() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
REQUIRE(task.t_id != 0);
// wait until the task completes
rv = norns_wait(&task);
- THEN("NORNS_SUCCESS is returned") {
+ THEN("norns_wait() returns NORNS_SUCCESS") {
REQUIRE(rv == NORNS_SUCCESS);
- THEN("symlink no longer exists and original file is left intact") {
+ THEN("symlink no longer exists and original file is left "
+ "intact") {
REQUIRE(!bfs::exists(p));
- REQUIRE(bfs::exists(env.get_from_namespace(nsid0, src_subdir1)));
+ REQUIRE(bfs::exists(
+ env.get_from_namespace(nsid0, src_subdir1)));
}
}
}
diff --git a/tests/api-send-command.cpp b/tests/api-send-command.cpp
index ab5d518592211836d48d68a63ba48059be63cdff..dcafdc92a0382510c99e110c2cd28ac246c35fe0 100644
--- a/tests/api-send-command.cpp
+++ b/tests/api-send-command.cpp
@@ -144,7 +144,7 @@ SCENARIO("send control commands to urd", "[api::nornsctl_send_command]") {
REQUIRE(rv == NORNS_ETASKSPENDING);
AND_WHEN("all tasks complete") {
- rv = norns_wait(&tasks[ntasks-1]);
+ rv = nornsctl_wait(&tasks[ntasks-1]);
THEN("nornsctl_send_command() returns NORNS_SUCCESS") {
rv = nornsctl_send_command(NORNSCTL_CMD_SHUTDOWN, NULL);
diff --git a/tests/api-task-init.cpp b/tests/api-task-init.cpp
index 15e6b48bd8f64f9ce0a27150b32e6b64a5b14a7b..1f07bb5849783460610ac987a2a766f7f44908ef 100644
--- a/tests/api-task-init.cpp
+++ b/tests/api-task-init.cpp
@@ -27,10 +27,10 @@
#include
#include "norns.h"
-#include "nornsctl.h"
#include "catch.hpp"
-SCENARIO("initialize a task with norns_iotask_init", "[api::norns_iotask_init]") {
+SCENARIO("initialize a task with norns_iotask_init",
+ "[api::norns_iotask_init]") {
GIVEN("invalid task information") {
WHEN("initializing a task with NULL src and dst") {
@@ -40,7 +40,7 @@ SCENARIO("initialize a task with norns_iotask_init", "[api::norns_iotask_init]")
norns_iotask_init(&task, task_op, NULL, NULL);
- THEN("task is set to 0") {
+ AND_THEN("task is set to 0") {
norns_iotask_t dummy;
memset(&dummy, 0, sizeof(dummy));
REQUIRE(memcmp(&task, &dummy, sizeof(norns_iotask_t)) == 0);
@@ -68,30 +68,9 @@ SCENARIO("initialize a task with norns_iotask_init", "[api::norns_iotask_init]")
}
}
-///XXX this case is no longer invalid
-/// GIVEN("invalid task information") {
-/// WHEN("initializing a task with a NULL dst") {
-///
-/// norns_iotask_t task;
-/// norns_op_t task_op = NORNS_IOTASK_COPY;
-///
-/// void* src_addr = (void*) 0xdeadbeef;
-/// size_t src_size = (size_t) 42;
-///
-/// norns_resource_t src = NORNS_MEMORY_REGION(src_addr, src_size);
-///
-/// norns_iotask_init(&task, task_op, &src, NULL);
-///
-/// THEN("task is set to 0") {
-/// norns_iotask_t dummy;
-/// memset(&dummy, 0, sizeof(dummy));
-/// REQUIRE(memcmp(&task, &dummy, sizeof(norns_iotask_t)) == 0);
-/// }
-/// }
-/// }
-
GIVEN("valid task information") {
- WHEN("initializing a task with src=NORNS_PROCESS_MEMORY and dst=NORNS_POSIX_PATH | R_LOCAL") {
+ WHEN("initializing a task with src=NORNS_PROCESS_MEMORY and "
+ "dst=NORNS_POSIX_PATH | R_LOCAL") {
norns_op_t task_op = NORNS_IOTASK_COPY;
void* src_addr = (void*) 0xdeadbeef;
@@ -116,14 +95,17 @@ SCENARIO("initialize a task with norns_iotask_init", "[api::norns_iotask_init]")
THEN("the norns_task structure is initialized as expected") {
REQUIRE(task.t_id == 0);
REQUIRE(task.t_op == task_op);
- REQUIRE(memcmp(&task.t_src, &src, sizeof(norns_resource_t)) == 0);
- REQUIRE(memcmp(&task.t_dst, &dst, sizeof(norns_resource_t)) == 0);
+ REQUIRE(memcmp(&task.t_src, &src,
+ sizeof(norns_resource_t)) == 0);
+ REQUIRE(memcmp(&task.t_dst, &dst,
+ sizeof(norns_resource_t)) == 0);
}
}
}
GIVEN("valid task information") {
- WHEN("initializing a task with src=NORNS_PROCESS_MEMORY and dst=NORNS_POSIX_PATH | R_REMOTE") {
+ WHEN("initializing a task with src=NORNS_PROCESS_MEMORY and "
+ "dst=NORNS_POSIX_PATH | R_REMOTE") {
norns_op_t task_op = NORNS_IOTASK_COPY;
void* src_addr = (void*) 0xdeadbeef;
@@ -149,17 +131,20 @@ SCENARIO("initialize a task with norns_iotask_init", "[api::norns_iotask_init]")
THEN("the norns_task structure is initialized as expected") {
REQUIRE(task.t_id == 0);
REQUIRE(task.t_op == task_op);
- REQUIRE(memcmp(&task.t_src, &src, sizeof(norns_resource_t)) == 0);
- REQUIRE(memcmp(&task.t_dst, &dst, sizeof(norns_resource_t)) == 0);
+ REQUIRE(memcmp(&task.t_src, &src,
+ sizeof(norns_resource_t)) == 0);
+ REQUIRE(memcmp(&task.t_dst, &dst,
+ sizeof(norns_resource_t)) == 0);
}
}
}
}
-SCENARIO("initialize a task with NORNS_TASK", "[api::NORNS_TASK]") {
+SCENARIO("initialize a task with NORNS_IOTASK", "[api::NORNS_IOTASK]") {
GIVEN("valid task information") {
- WHEN("initializing a task with src=NORNS_MEMORY_REGION and dst=NORNS_LOCAL_PATH") {
+ WHEN("initializing a task with src=NORNS_MEMORY_REGION and "
+ "dst=NORNS_LOCAL_PATH") {
norns_op_t task_op = NORNS_IOTASK_COPY;
void* src_addr = (void*) 0xdeadbeef;
@@ -167,9 +152,10 @@ SCENARIO("initialize a task with NORNS_TASK", "[api::NORNS_TASK]") {
const char* dst_nsid = "tmp://";
const char* dst_path = "/a/b/c";
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_MEMORY_REGION(src_addr, src_size),
- NORNS_LOCAL_PATH(dst_nsid, dst_path));
+ norns_iotask_t task =
+ NORNS_IOTASK(task_op,
+ NORNS_MEMORY_REGION(src_addr, src_size),
+ NORNS_LOCAL_PATH(dst_nsid, dst_path));
THEN("the norns_task structure is initialized as expected") {
REQUIRE(task.t_id == 0);
@@ -182,7 +168,8 @@ SCENARIO("initialize a task with NORNS_TASK", "[api::NORNS_TASK]") {
}
}
- WHEN("initializing a task with src=NORNS_PROCESS_MEMORY and dst=NORNS_REMOTE_PATH") {
+ WHEN("initializing a task with src=NORNS_PROCESS_MEMORY and "
+ "dst=NORNS_REMOTE_PATH") {
norns_op_t task_op = NORNS_IOTASK_COPY;
void* src_addr = (void*) 0xdeadbeef;
size_t src_size = (size_t) 42;
@@ -190,9 +177,10 @@ SCENARIO("initialize a task with NORNS_TASK", "[api::NORNS_TASK]") {
const char* dst_host = "node0";
const char* dst_path = "/a/b/c";
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_MEMORY_REGION(src_addr, src_size),
- NORNS_REMOTE_PATH(dst_nsid, dst_host, dst_path));
+ norns_iotask_t task =
+ NORNS_IOTASK(task_op,
+ NORNS_MEMORY_REGION(src_addr, src_size),
+ NORNS_REMOTE_PATH(dst_nsid, dst_host, dst_path));
THEN("the norns_task structure is initialized as expected") {
REQUIRE(task.t_id == 0);
@@ -207,7 +195,8 @@ SCENARIO("initialize a task with NORNS_TASK", "[api::NORNS_TASK]") {
}
- WHEN("initializing a task with src=NORNS_MEMORY_REGION and dst=NORNS_LOCAL_PATH") {
+ WHEN("initializing a task with src=NORNS_MEMORY_REGION and "
+ "dst=NORNS_LOCAL_PATH") {
norns_op_t task_op = NORNS_IOTASK_COPY;
void* src_addr = (void*) 0xdeadbeef;
@@ -215,9 +204,10 @@ SCENARIO("initialize a task with NORNS_TASK", "[api::NORNS_TASK]") {
const char* dst_nsid = "tmp://";
const char* dst_path = "/a/b/c";
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_MEMORY_REGION(src_addr, src_size),
- NORNS_SHARED_PATH(dst_nsid, dst_path));
+ norns_iotask_t task =
+ NORNS_IOTASK(task_op,
+ NORNS_MEMORY_REGION(src_addr, src_size),
+ NORNS_SHARED_PATH(dst_nsid, dst_path));
THEN("the norns_task structure is initialized as expected") {
REQUIRE(task.t_id == 0);
@@ -231,4 +221,3 @@ SCENARIO("initialize a task with NORNS_TASK", "[api::NORNS_TASK]") {
}
}
}
-
diff --git a/tests/api-task-status.cpp b/tests/api-task-status.cpp
index c99e397e6e697fa3f0e1fa5d89f9d56f8da8b99b..d5998e5afc14e535b74aeef275dba1a3055f98b9 100644
--- a/tests/api-task-status.cpp
+++ b/tests/api-task-status.cpp
@@ -27,11 +27,10 @@
#include "norns.h"
-#include "nornsctl.h"
#include "test-env.hpp"
#include "catch.hpp"
-SCENARIO("check request", "[api::norns_status]") {
+SCENARIO("check request", "[api::norns_error]") {
GIVEN("a running urd instance") {
test_env env(
@@ -45,8 +44,10 @@ SCENARIO("check request", "[api::norns_status]") {
bfs::path src_mnt, dst_mnt;
// create namespaces
- std::tie(std::ignore, src_mnt) = env.create_namespace(nsid0, "mnt/tmp0", 16384);
- std::tie(std::ignore, dst_mnt) = env.create_namespace(nsid1, "mnt/tmp1", 16384);
+ std::tie(std::ignore, src_mnt) =
+ env.create_namespace(nsid0, "mnt/tmp0", 16384);
+ std::tie(std::ignore, dst_mnt) =
+ env.create_namespace(nsid1, "mnt/tmp1", 16384);
// define input names
std::vector input_data(100, 42);
@@ -61,17 +62,16 @@ SCENARIO("check request", "[api::norns_status]") {
// create input data
env.add_to_namespace(nsid0, "/a/b/c/file", 4096);
- /**************************************************************************************************************/
- /* tests for error conditions */
- /**************************************************************************************************************/
+ /**********************************************************************/
+ /* tests for error conditions */
+ /**********************************************************************/
WHEN("checking the status of an active request") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_MEMORY_REGION(src_buf, src_buf_size),
- NORNS_LOCAL_PATH(nsid1, dst_file.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_MEMORY_REGION(src_buf, src_buf_size),
+ NORNS_LOCAL_PATH(nsid1, dst_file.c_str()));
norns_error_t rv = norns_submit(&task);
@@ -80,7 +80,7 @@ SCENARIO("check request", "[api::norns_status]") {
REQUIRE(task.t_id != 0);
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
THEN("NORNS_SUCCESS is returned and task status is valid") {
REQUIRE(rv == NORNS_SUCCESS);
@@ -93,11 +93,10 @@ SCENARIO("check request", "[api::norns_status]") {
WHEN("checking the status of an active request") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- norns_iotask_t task = NORNS_IOTASK(task_op,
- NORNS_LOCAL_PATH(nsid0, src_file.c_str()),
- NORNS_LOCAL_PATH(nsid1, dst_file.c_str()));
+ norns_iotask_t task =
+ NORNS_IOTASK(NORNS_IOTASK_COPY,
+ NORNS_LOCAL_PATH(nsid0, src_file.c_str()),
+ NORNS_LOCAL_PATH(nsid1, dst_file.c_str()));
norns_error_t rv = norns_submit(&task);
@@ -107,7 +106,7 @@ SCENARIO("check request", "[api::norns_status]") {
retry:
norns_stat_t stats;
- rv = norns_status(&task, &stats);
+ rv = norns_error(&task, &stats);
THEN("NORNS_SUCCESS is returned and task status is valid") {
REQUIRE(rv == NORNS_SUCCESS);
@@ -125,15 +124,13 @@ retry:
/*
WHEN("submitting a request to copy data using unregistered backends") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
void* src_addr = (void*) 0xdeadbeef;
size_t src_size = (size_t) 42;
const char* dst_nsid = "tmp://";
const char* dst_path = "/a/b/c";
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_COPY,
NORNS_MEMORY_REGION(src_addr, src_size),
NORNS_LOCAL_PATH(dst_nsid, dst_path));
@@ -146,8 +143,6 @@ retry:
WHEN("submitting a request to copy data using an unregistered src backend") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
const char* src_nsid = "tmp://";
const char* src_mnt = "/mnt/tmp0";
const char* src_path = "/a/b/c";
@@ -162,7 +157,7 @@ retry:
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_COPY,
NORNS_LOCAL_PATH(src_nsid, src_path),
NORNS_SHARED_PATH(dst_nsid, dst_path));
@@ -179,8 +174,6 @@ retry:
WHEN("submitting a request to copy data using an unregistered dst backend") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
const char* src_nsid = "tmp://";
const char* src_mnt = "/mnt/tmp0";
const char* src_path = "/a/b/c";
@@ -194,7 +187,7 @@ retry:
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_COPY,
NORNS_LOCAL_PATH(src_nsid, src_path),
NORNS_SHARED_PATH(dst_nsid, dst_path));
@@ -218,8 +211,6 @@ retry:
/* copy from process memory to .* */
WHEN("submitting a request to copy from NORNS_PROCESS_MEMORY to NORNS_LOCAL_PATH") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
const char* src_nsid = "mem://";
void* src_addr = (void*) 0xdeadbeef;
size_t src_size = (size_t) 42;
@@ -232,7 +223,7 @@ retry:
norns_error_t rv = nornsctl_register_namespace(&bdst);
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_COPY,
NORNS_MEMORY_REGION(src_nsid, src_addr, src_size),
NORNS_LOCAL_PATH(dst_nsid, dst_path));
@@ -253,8 +244,6 @@ retry:
WHEN("submitting a request to copy from NORNS_PROCESS_MEMORY to NORNS_SHARED_PATH") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
const char* src_nsid = "mem://";
void* src_addr = (void*) 0xdeadbeef;
size_t src_size = (size_t) 42;
@@ -268,7 +257,7 @@ retry:
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_COPY,
NORNS_MEMORY_REGION(src_nsid, src_addr, src_size),
NORNS_SHARED_PATH(dst_nsid, dst_path));
@@ -289,8 +278,6 @@ retry:
WHEN("submitting a request to copy from NORNS_PROCESS_MEMORY to NORNS_REMOTE_PATH") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
const char* src_nsid = "mem://";
void* src_addr = (void*) 0xdeadbeef;
size_t src_size = (size_t) 42;
@@ -305,7 +292,7 @@ retry:
REQUIRE(rv == NORNS_SUCCESS);
*/
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_COPY,
NORNS_MEMORY_REGION(src_nsid, src_addr, src_size),
NORNS_REMOTE_PATH(dst_nsid, dst_host, dst_path));
@@ -324,8 +311,6 @@ retry:
/* copy from local path to .* */
WHEN("submitting a request to copy from NORNS_LOCAL_PATH to NORNS_LOCAL_PATH") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
const char* src_nsid = "tmp0://";
const char* src_mnt = "/mnt/tmp0";
const char* src_path = "/b/c/d";
@@ -342,7 +327,7 @@ retry:
rv = nornsctl_register_namespace(&bdst);
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_COPY,
NORNS_LOCAL_PATH(src_nsid, src_path),
NORNS_LOCAL_PATH(dst_nsid, dst_path));
@@ -363,8 +348,6 @@ retry:
WHEN("submitting a request to copy from NORNS_LOCAL_PATH to NORNS_SHARED_PATH") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
const char* src_nsid = "tmp://";
const char* src_mnt = "/mnt/tmp";
const char* src_path = "/b/c/d";
@@ -381,7 +364,7 @@ retry:
rv = nornsctl_register_namespace(&bdst);
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_COPY,
NORNS_LOCAL_PATH(src_nsid, src_path),
NORNS_SHARED_PATH(dst_nsid, dst_path));
@@ -402,8 +385,6 @@ retry:
WHEN("submitting a request to copy from NORNS_LOCAL_PATH to NORNS_REMOTE_PATH") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
const char* src_nsid = "tmp://";
const char* src_mnt = "/mnt/tmp";
const char* src_path = "/b/c/d";
@@ -423,7 +404,7 @@ retry:
REQUIRE(rv == NORNS_SUCCESS);
*/
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_COPY,
NORNS_LOCAL_PATH(src_nsid, src_path),
NORNS_REMOTE_PATH(dst_nsid, dst_host, dst_path));
@@ -442,8 +423,6 @@ retry:
/* using a remote node as source is not allowed (yet) */
WHEN("submitting a request to copy from NORNS_REMOTE_PATH to NORNS_LOCAL_PATH") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
const char* src_nsid = "tmp://";
const char* src_host = "node0";
const char* src_path = "/a/b/c";
@@ -456,7 +435,7 @@ retry:
norns_error_t rv = nornsctl_register_namespace(&bdst);
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_COPY,
NORNS_REMOTE_PATH(src_nsid, src_host, src_path),
NORNS_LOCAL_PATH(dst_nsid, dst_path));
@@ -474,8 +453,6 @@ retry:
/* using a remote node as source is not allowed (yet) */
WHEN("submitting a request to copy from NORNS_REMOTE_PATH to NORNS_SHARED_PATH") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
const char* src_nsid = "tmp://";
const char* src_host = "node0";
const char* src_path = "/a/b/c";
@@ -488,7 +465,7 @@ retry:
norns_error_t rv = nornsctl_register_namespace(&bdst);
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_COPY,
NORNS_REMOTE_PATH(src_nsid, src_host, src_path),
NORNS_SHARED_PATH(dst_nsid, dst_path));
@@ -506,8 +483,6 @@ retry:
/* using a remote node as source is not allowed (yet) */
WHEN("submitting a request to copy from NORNS_REMOTE_PATH to NORNS_REMOTE_PATH") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
const char* src_nsid = "tmp://";
const char* src_host = "node0";
const char* src_path = "/a/b/c";
@@ -516,7 +491,7 @@ retry:
const char* dst_host = "node1";
const char* dst_path = "/b/c/d";
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_COPY,
NORNS_REMOTE_PATH(src_nsid, src_host, src_path),
NORNS_REMOTE_PATH(dst_nsid, dst_host, dst_path));
@@ -530,8 +505,6 @@ retry:
/* using the process memory as destination is not allowed (yet) */
WHEN("submitting a request to copy from NORNS_LOCAL_PATH to NORNS_PROCESS_MEMORY") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
const char* src_nsid = "tmp://";
const char* src_mnt = "/mnt/tmp";
const char* src_path = "/a/b/c";
@@ -545,7 +518,7 @@ retry:
norns_error_t rv = nornsctl_register_namespace(&bsrc);
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_COPY,
NORNS_LOCAL_PATH(src_nsid, src_path),
NORNS_MEMORY_REGION(dst_nsid, dst_addr, dst_size));
@@ -566,8 +539,6 @@ retry:
/* using the process memory as destination is not allowed (yet) */
WHEN("submitting a request to copy from NORNS_SHARED_PATH to NORNS_PROCESS_MEMORY") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
const char* src_nsid = "lustre://";
const char* src_mnt = "/mnt/lustre";
const char* src_path = "/a/b/c";
@@ -581,7 +552,7 @@ retry:
norns_error_t rv = nornsctl_register_namespace(&bsrc);
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_COPY,
NORNS_SHARED_PATH(src_nsid, src_path),
NORNS_MEMORY_REGION(dst_nsid, dst_addr, dst_size));
@@ -602,8 +573,6 @@ retry:
/* using the process memory as destination is not allowed (yet) */
WHEN("submitting a request to copy from NORNS_REMOTE_PATH to NORNS_PROCESS_MEMORY") {
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
const char* src_nsid = "tmp://";
const char* src_host = "node0";
const char* src_path = "/a/b/c";
@@ -612,7 +581,7 @@ retry:
void* dst_addr = (void*) 0xdeadbeef;
size_t dst_size = (size_t) 42;
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_COPY,
NORNS_REMOTE_PATH(src_nsid, src_host, src_path),
NORNS_MEMORY_REGION(dst_nsid, dst_addr, dst_size));
@@ -633,8 +602,6 @@ retry:
/* move from process memory to .* */
WHEN("submitting a request to move from NORNS_PROCESS_MEMORY to NORNS_LOCAL_PATH") {
- norns_op_t task_op = NORNS_IOTASK_MOVE;
-
const char* src_nsid = "mem://";
void* src_addr = (void*) 0xdeadbeef;
size_t src_size = (size_t) 42;
@@ -647,7 +614,7 @@ retry:
norns_error_t rv = nornsctl_register_namespace(&bdst);
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_MOVE,
NORNS_MEMORY_REGION(src_nsid, src_addr, src_size),
NORNS_LOCAL_PATH(dst_nsid, dst_path));
@@ -668,8 +635,6 @@ retry:
WHEN("submitting a request to move from NORNS_PROCESS_MEMORY to NORNS_SHARED_PATH") {
- norns_op_t task_op = NORNS_IOTASK_MOVE;
-
const char* src_nsid = "mem://";
void* src_addr = (void*) 0xdeadbeef;
size_t src_size = (size_t) 42;
@@ -683,7 +648,7 @@ retry:
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_MOVE,
NORNS_MEMORY_REGION(src_nsid, src_addr, src_size),
NORNS_SHARED_PATH(dst_nsid, dst_path));
@@ -704,8 +669,6 @@ retry:
WHEN("submitting a request to move from NORNS_PROCESS_MEMORY to NORNS_REMOTE_PATH") {
- norns_op_t task_op = NORNS_IOTASK_MOVE;
-
const char* src_nsid = "mem://";
void* src_addr = (void*) 0xdeadbeef;
size_t src_size = (size_t) 42;
@@ -720,7 +683,7 @@ retry:
REQUIRE(rv == NORNS_SUCCESS);
*/
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_MOVE,
NORNS_MEMORY_REGION(src_nsid, src_addr, src_size),
NORNS_REMOTE_PATH(dst_nsid, dst_host, dst_path));
@@ -739,8 +702,6 @@ retry:
/* move from local path to .* */
WHEN("submitting a request to move from NORNS_LOCAL_PATH to NORNS_LOCAL_PATH") {
- norns_op_t task_op = NORNS_IOTASK_MOVE;
-
const char* src_nsid = "tmp0://";
const char* src_mnt = "/mnt/tmp0";
const char* src_path = "/b/c/d";
@@ -757,7 +718,7 @@ retry:
rv = nornsctl_register_namespace(&bdst);
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_MOVE,
NORNS_LOCAL_PATH(src_nsid, src_path),
NORNS_LOCAL_PATH(dst_nsid, dst_path));
@@ -778,8 +739,6 @@ retry:
WHEN("submitting a request to move from NORNS_LOCAL_PATH to NORNS_SHARED_PATH") {
- norns_op_t task_op = NORNS_IOTASK_MOVE;
-
const char* src_nsid = "tmp://";
const char* src_mnt = "/mnt/tmp";
const char* src_path = "/b/c/d";
@@ -796,7 +755,7 @@ retry:
rv = nornsctl_register_namespace(&bdst);
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_MOVE,
NORNS_LOCAL_PATH(src_nsid, src_path),
NORNS_SHARED_PATH(dst_nsid, dst_path));
@@ -817,8 +776,6 @@ retry:
WHEN("submitting a request to move from NORNS_LOCAL_PATH to NORNS_REMOTE_PATH") {
- norns_op_t task_op = NORNS_IOTASK_MOVE;
-
const char* src_nsid = "tmp://";
const char* src_mnt = "/mnt/tmp";
const char* src_path = "/b/c/d";
@@ -838,7 +795,7 @@ retry:
REQUIRE(rv == NORNS_SUCCESS);
*/
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_MOVE,
NORNS_LOCAL_PATH(src_nsid, src_path),
NORNS_REMOTE_PATH(dst_nsid, dst_host, dst_path));
@@ -857,8 +814,6 @@ retry:
/* using a remote node as source is not allowed (yet) */
WHEN("submitting a request to move from NORNS_REMOTE_PATH to NORNS_LOCAL_PATH") {
- norns_op_t task_op = NORNS_IOTASK_MOVE;
-
const char* src_nsid = "tmp://";
const char* src_host = "node0";
const char* src_path = "/a/b/c";
@@ -871,7 +826,7 @@ retry:
norns_error_t rv = nornsctl_register_namespace(&bdst);
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_MOVE,
NORNS_REMOTE_PATH(src_nsid, src_host, src_path),
NORNS_LOCAL_PATH(dst_nsid, dst_path));
@@ -889,8 +844,6 @@ retry:
/* using a remote node as source is not allowed (yet) */
WHEN("submitting a request to move from NORNS_REMOTE_PATH to NORNS_SHARED_PATH") {
- norns_op_t task_op = NORNS_IOTASK_MOVE;
-
const char* src_nsid = "tmp://";
const char* src_host = "node0";
const char* src_path = "/a/b/c";
@@ -903,7 +856,7 @@ retry:
norns_error_t rv = nornsctl_register_namespace(&bdst);
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_MOVE,
NORNS_REMOTE_PATH(src_nsid, src_host, src_path),
NORNS_SHARED_PATH(dst_nsid, dst_path));
@@ -921,8 +874,6 @@ retry:
/* using a remote node as source is not allowed (yet) */
WHEN("submitting a request to move from NORNS_REMOTE_PATH to NORNS_REMOTE_PATH") {
- norns_op_t task_op = NORNS_IOTASK_MOVE;
-
const char* src_nsid = "tmp://";
const char* src_host = "node0";
const char* src_path = "/a/b/c";
@@ -931,7 +882,7 @@ retry:
const char* dst_host = "node1";
const char* dst_path = "/b/c/d";
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_MOVE,
NORNS_REMOTE_PATH(src_nsid, src_host, src_path),
NORNS_REMOTE_PATH(dst_nsid, dst_host, dst_path));
@@ -945,8 +896,6 @@ retry:
/* using the process memory as destination is not allowed (yet) */
WHEN("submitting a request to move from NORNS_LOCAL_PATH to NORNS_PROCESS_MEMORY") {
- norns_op_t task_op = NORNS_IOTASK_MOVE;
-
const char* src_nsid = "tmp://";
const char* src_mnt = "/mnt/tmp";
const char* src_path = "/a/b/c";
@@ -960,7 +909,7 @@ retry:
norns_error_t rv = nornsctl_register_namespace(&bsrc);
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_MOVE,
NORNS_LOCAL_PATH(src_nsid, src_path),
NORNS_MEMORY_REGION(dst_nsid, dst_addr, dst_size));
@@ -981,8 +930,6 @@ retry:
/* using the process memory as destination is not allowed (yet) */
WHEN("submitting a request to move from NORNS_SHARED_PATH to NORNS_PROCESS_MEMORY") {
- norns_op_t task_op = NORNS_IOTASK_MOVE;
-
const char* src_nsid = "lustre://";
const char* src_mnt = "/mnt/lustre";
const char* src_path = "/a/b/c";
@@ -996,7 +943,7 @@ retry:
norns_error_t rv = nornsctl_register_namespace(&bsrc);
REQUIRE(rv == NORNS_SUCCESS);
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_MOVE,
NORNS_SHARED_PATH(src_nsid, src_path),
NORNS_MEMORY_REGION(dst_nsid, dst_addr, dst_size));
@@ -1017,8 +964,6 @@ retry:
/* using the process memory as destination is not allowed (yet) */
WHEN("submitting a request to move from NORNS_REMOTE_PATH to NORNS_PROCESS_MEMORY") {
- norns_op_t task_op = NORNS_IOTASK_MOVE;
-
const char* src_nsid = "tmp://";
const char* src_host = "node0";
const char* src_path = "/a/b/c";
@@ -1027,7 +972,7 @@ retry:
void* dst_addr = (void*) 0xdeadbeef;
size_t dst_size = (size_t) 42;
- norns_iotask_t task = NORNS_IOTASK(task_op,
+ norns_iotask_t task = NORNS_IOTASK(NORNS_IOTASK_MOVE,
NORNS_REMOTE_PATH(src_nsid, src_host, src_path),
NORNS_MEMORY_REGION(dst_nsid, dst_addr, dst_size));
@@ -1063,125 +1008,3 @@ retry:
}
#endif
}
-
-
-SCENARIO("check requests", "[api::nornsctl_status]") {
- GIVEN("a running urd instance") {
-
- test_env env(
- fake_daemon_cfg {
- true /* dry_run? */
- }
- );
-
- const char* nsid0 = "tmp0";
- const char* nsid1 = "tmp1";
- bfs::path src_mnt, dst_mnt;
-
- // create namespaces
- std::tie(std::ignore, src_mnt) = env.create_namespace(nsid0, "mnt/tmp0", 16384);
- std::tie(std::ignore, dst_mnt) = env.create_namespace(nsid1, "mnt/tmp1", 16384);
-
- // define input names
- void* src_buf;
- size_t src_buf_size __attribute__((unused));
- const bfs::path src_file = "/a/b/c/file";
- size_t src_file_size = 4096;
-
- // define output names
- const bfs::path dst_file = "/b/c/d/file";
-
- // create input data
- env.add_to_namespace(nsid0, src_file, 4096);
-
- // 64MiB buffer
- std::vector input_data(16*1024*1024, 42);
- src_buf = input_data.data();
- src_buf_size = input_data.size() * sizeof(int);
-
- WHEN("checking the status of all requests without actual requests running") {
- nornsctl_stat_t global_stats;
- norns_error_t rv = nornsctl_status(&global_stats);
- REQUIRE(rv == NORNS_SUCCESS);
- REQUIRE(global_stats.st_pending_tasks == 0);
- REQUIRE(global_stats.st_running_tasks == 0);
- REQUIRE(global_stats.st_eta == 0.0);
- }
-
- WHEN("checking the status of all requests") {
-
- norns_op_t task_op = NORNS_IOTASK_COPY;
-
- const size_t ntasks = 10;
- norns_iotask_t tasks[ntasks];
- size_t sizes[] = { 4*1024*1024, 16*1024*1024, 32*1024*1024, 64*1024*1024 };
-
- for(size_t i=0; i