changeset 22271:5c7987bec546

lib: Add unit test for file_create_locked()
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Wed, 28 Jun 2017 17:40:20 +0300
parents 5b108ca20b05
children 651fa80715a3
files src/lib/Makefile.am src/lib/test-file-create-locked.c src/lib/test-lib.c src/lib/test-lib.h
diffstat 4 files changed, 94 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/Makefile.am	Thu Jun 22 01:52:29 2017 +0300
+++ b/src/lib/Makefile.am	Wed Jun 28 17:40:20 2017 +0300
@@ -320,6 +320,7 @@
 	test-crc32.c \
 	test-data-stack.c \
 	test-failures.c \
+	test-file-create-locked.c \
 	test-guid.c \
 	test-hash.c \
 	test-hash-format.c \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/test-file-create-locked.c	Wed Jun 28 17:40:20 2017 +0300
@@ -0,0 +1,91 @@
+/* Copyright (c) 2017 Dovecot authors, see the included COPYING file */
+
+#include "test-lib.h"
+#include "file-create-locked.h"
+
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/stat.h>
+
+static void create_file(const char *path)
+{
+	int fd;
+
+	fd = creat(path, 0600);
+	if (fd == -1)
+		i_fatal("creat(%s) failed: %m", path);
+	i_close_fd(&fd);
+}
+
+static bool wait_for_file(pid_t pid, const char *path)
+{
+	struct stat st;
+
+	for (unsigned int i = 0; i < 1000; i++) {
+		if (stat(path, &st) == 0)
+			return TRUE;
+		if (errno != ENOENT)
+			i_fatal("stat(%s) failed: %m", path);
+		if (kill(pid, 0) < 0) {
+			if (errno == ESRCH)
+				return FALSE;
+			i_fatal("kill(SIGSRCH) failed: %m");
+		}
+		usleep(10000);
+	}
+	i_error("%s isn't being created", path);
+	return FALSE;
+}
+
+static void test_file_create_locked_basic(void)
+{
+	struct file_create_settings set = {
+		.lock_timeout_secs = 0,
+		.lock_method = FILE_LOCK_METHOD_FCNTL,
+	};
+	const char *path = ".test-file-create-locked";
+	struct file_lock *lock;
+	const char *error;
+	bool created;
+	pid_t pid;
+	int fd;
+
+	test_begin("file_create_locked()");
+
+	i_unlink_if_exists(path);
+	i_unlink_if_exists(".test-temp-file-create-locked-child");
+	pid = fork();
+	switch (pid) {
+	case (pid_t)-1:
+		i_error("fork() failed: %m");
+		break;
+	case 0:
+		/* child */
+		fd = file_create_locked(path, &set, &lock, &created, &error);
+		test_assert(fd > 0);
+		test_assert(created);
+		if (test_has_failed())
+			exit(1);
+		create_file(".test-temp-file-create-locked-child");
+		sleep(60);
+		i_close_fd(&fd);
+		exit(0);
+	default:
+		/* parent */
+		test_assert(wait_for_file(pid, ".test-temp-file-create-locked-child"));
+		if (test_has_failed())
+			break;
+		test_assert(file_create_locked(path, &set, &lock, &created, &error) == -1);
+		test_assert(errno == EAGAIN);
+		if (kill(pid, SIGKILL) < 0)
+			i_error("kill(SIGKILL) failed: %m");
+		break;
+	}
+	i_unlink_if_exists(".test-temp-file-create-locked-child");
+	test_end();
+}
+
+void test_file_create_locked(void)
+{
+	test_file_create_locked_basic();
+}
--- a/src/lib/test-lib.c	Thu Jun 22 01:52:29 2017 +0300
+++ b/src/lib/test-lib.c	Wed Jun 28 17:40:20 2017 +0300
@@ -15,6 +15,7 @@
 		test_crc32,
 		test_data_stack,
 		test_failures,
+		test_file_create_locked,
 		test_guid,
 		test_hash,
 		test_hash_format,
--- a/src/lib/test-lib.h	Thu Jun 22 01:52:29 2017 +0300
+++ b/src/lib/test-lib.h	Wed Jun 28 17:40:20 2017 +0300
@@ -16,6 +16,7 @@
 void test_data_stack(void);
 enum fatal_test_state fatal_data_stack(unsigned int);
 void test_failures(void);
+void test_file_create_locked(void);
 void test_guid(void);
 void test_hash(void);
 void test_hash_format(void);