* [LTP] [PATCH v3 1/2] lib: add FILE_PRINTF
@ 2016-12-10 20:29 Petr Vorel
2016-12-10 20:29 ` [LTP] [PATCH v3 2/2] syscalls/mq_open: fix old tests + convert to use new API Petr Vorel
0 siblings, 1 reply; 4+ messages in thread
From: Petr Vorel @ 2016-12-10 20:29 UTC (permalink / raw)
To: ltp
Using non-safe version is handy in cleanup.
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
include/tst_safe_file_ops.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/tst_safe_file_ops.h b/include/tst_safe_file_ops.h
index 2e4067ca1..cb8f25dcd 100644
--- a/include/tst_safe_file_ops.h
+++ b/include/tst_safe_file_ops.h
@@ -38,6 +38,10 @@
file_lines_scanf(__FILE__, __LINE__, NULL, 1,\
(path), (fmt), ## __VA_ARGS__)
+#define FILE_PRINTF(path, fmt, ...) \
+ file_printf(__FILE__, __LINE__, \
+ (path), (fmt), ## __VA_ARGS__)
+
#define SAFE_FILE_PRINTF(path, fmt, ...) \
safe_file_printf(__FILE__, __LINE__, NULL, \
(path), (fmt), ## __VA_ARGS__)
--
2.11.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [LTP] [PATCH v3 2/2] syscalls/mq_open: fix old tests + convert to use new API
2016-12-10 20:29 [LTP] [PATCH v3 1/2] lib: add FILE_PRINTF Petr Vorel
@ 2016-12-10 20:29 ` Petr Vorel
2016-12-15 13:52 ` Cyril Hrubis
0 siblings, 1 reply; 4+ messages in thread
From: Petr Vorel @ 2016-12-10 20:29 UTC (permalink / raw)
To: ltp
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
Hope it's not too complicated. cleanup(void) doesn't use any SAFE_* function, that's why they're two functions.
---
testcases/kernel/syscalls/mq_open/mq_open01.c | 626 ++++++++++----------------
testcases/kernel/syscalls/utils/common_j_h.c | 107 -----
testcases/kernel/syscalls/utils/include_j_h.h | 6 -
3 files changed, 238 insertions(+), 501 deletions(-)
diff --git a/testcases/kernel/syscalls/mq_open/mq_open01.c b/testcases/kernel/syscalls/mq_open/mq_open01.c
index 1ab818535..5fd140985 100644
--- a/testcases/kernel/syscalls/mq_open/mq_open01.c
+++ b/testcases/kernel/syscalls/mq_open/mq_open01.c
@@ -1,129 +1,43 @@
-/******************************************************************************/
-/* Copyright (c) Crackerjack Project., 2007-2008 ,Hitachi, Ltd */
-/* Author(s): Takahiro Yasui <takahiro.yasui.mp@hitachi.com>, */
-/* Yumiko Sugita <yumiko.sugita.yf@hitachi.com>, */
-/* Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp> */
-/* */
-/* This program is free software; you can redistribute it and/or modify */
-/* it under the terms of the GNU General Public License as published by */
-/* the Free Software Foundation; either version 2 of the License, or */
-/* (at your option) any later version. */
-/* */
-/* This program 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 General Public License for more details. */
-/* */
-/* You should have received a copy of the GNU General Public License */
-/* along with this program; if not, write to the Free Software */
-/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-/* */
-/******************************************************************************/
-/******************************************************************************/
-/* */
-/* File: mq_open01.c */
-/* */
-/* Description: This tests the mq_open() syscall */
-/* */
-/* */
-/* */
-/* */
-/* */
-/* */
-/* Usage: <for command-line> */
-/* mq_open01 [-c n] [-e][-i n] [-I x] [-p x] [-t] */
-/* where, -c n : Run n copies concurrently. */
-/* -e : Turn on errno logging. */
-/* -i n : Execute test n times. */
-/* -I x : Execute test for x seconds. */
-/* -P x : Pause for x seconds between iterations. */
-/* -t : Turn on syscall timing. */
-/* */
-/* Total Tests: 1 */
-/* */
-/* Test Name: mq_open01 */
-/* History: Porting from Crackerjack to LTP is done by */
-/* Manas Kumar Nayak maknayak@in.ibm.com> */
-/******************************************************************************/
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/uio.h>
-#include <getopt.h>
-#include <stdlib.h>
+/*
+ * Copyright (c) Crackerjack Project., 2007-2008 ,Hitachi, Ltd
+ * Author(s): Takahiro Yasui <takahiro.yasui.mp@hitachi.com>,
+ * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>,
+ * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp>
+ * Copyright (c) 2016 Linux Test Project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
#include <errno.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
#include <mqueue.h>
-#include <limits.h>
-
-#include "../utils/include_j_h.h"
-#include "../utils/common_j_h.c"
-
-#include "test.h"
-#include "linux_syscall_numbers.h"
-
-char *TCID = "mq_open01";
-int testno;
-int TST_TOTAL = 1;
-
-/* Extern Global Functions */
-/******************************************************************************/
-/* */
-/* Function: cleanup */
-/* */
-/* Description: Performs all one time clean up for this test on successful */
-/* completion, premature exit or failure. Closes all temporary */
-/* files, removes all temporary directories exits the test with */
-/* appropriate return code by calling tst_exit() function. */
-/* */
-/* Input: None. */
-/* */
-/* Output: None. */
-/* */
-/* Return: On failure - Exits calling tst_exit(). Non '0' return code. */
-/* On success - Exits calling tst_exit(). With '0' return code. */
-/* */
-/******************************************************************************/
-void cleanup(void)
-{
+#include <pwd.h>
- tst_rmdir();
-}
+#include "tst_safe_file_ops.h"
+#include "tst_test.h"
-/* Local Functions */
-/******************************************************************************/
-/* */
-/* Function: setup */
-/* */
-/* Description: Performs all one time setup for this test. This function is */
-/* typically used to capture signals, create temporary dirs */
-/* and temporary files that may be used in the course of this */
-/* test. */
-/* */
-/* Input: None. */
-/* */
-/* Output: None. */
-/* */
-/* Return: On failure - Exits by calling cleanup(). */
-/* On success - returns 0. */
-/* */
-/******************************************************************************/
-void setup(void)
-{
- tst_require_root();
+#define QUEUE_NAME "/test_mqueue"
- /* Capture signals if any */
- /* Create temporary directories */
- TEST_PAUSE;
- tst_tmpdir();
-}
+static uid_t euid;
+static struct passwd *pw;
+static char *qname;
+static struct rlimit rlim;
-/*
- * Macros
- */
-#define SYSCALL_NAME "mq_open"
+static int fd1;
+static int fd2;
+static int oldlim;
+static int max_queues;
enum test_type {
NORMAL,
@@ -131,307 +45,243 @@ enum test_type {
NO_SPACE,
};
-/*
- * Data Structure
- */
+#define TYPE_NAME(x) .ttype = x, .desc = #x
struct test_case {
int ttype;
- char *user;
+ const char *desc;
+ int as_nobody;
char *qname;
int oflag;
- long mq_maxmsg; // Maximum numebr of messages.
- long mq_msgsize; // Maximum message size.
+ struct mq_attr rq;
int ret;
int err;
};
-#define ULIMIT_FNUM 0
+#define NOFILE_LIMIT 0
#define PROC_MAX_QUEUES "/proc/sys/fs/mqueue/queues_max"
-/* Test cases
- *
- * test status of errors on man page
- *
- * EACCES v (permission is denied)
- * EEXIST v (named message queue already exists)
- * EINTR --- (interrupted by a signal)
- * EINVAL v (not supported for the given name, or invalid
- * arguments)
- * EMFILE v (process file table overflow)
- * ENAMETOOLONG v (too long name length)
- * ENFILE can't check because it's difficult to create no-fd
- * ENOENT v (O_CREAT is not set and the named message queue
- * does not exist)
- * ENOSPC v (no space for the new message queue)
- */
-
static struct test_case tcase[] = {
-#if 1
- { // case00
- .ttype = NORMAL,
- .qname = QUEUE_NAME,
- .oflag = O_CREAT,
- .mq_maxmsg = 20,
- .mq_msgsize = 16384,
- .ret = 0,
- .err = 0,
- },
-#else
- { // case00
- .ttype = NORMAL,
- .qname = QUEUE_NAME,
- .oflag = O_CREAT,
- .ret = 0,
- .err = 0,
- },
- { // case01
- .ttype = NORMAL,
- // 0 1 2 3
- // 0123456789012345678901234567890123456789
- "aaaaaaaaaaaaaaa",
- .oflag = O_CREAT,
- .ret = 0,
- .err = 0,
- },
- { // case02
- .ttype = NORMAL,
- // 0 1 2 3
- // 0123456789012345678901234567890123456789
- "aaaaaaaaaaaaaaaa",
- .oflag = O_CREAT,
- .ret = -1,
- .err = ENAMETOOLONG,
- },
-
- { // case03
- .ttype = NORMAL,
- .qname = "",
- .oflag = O_CREAT,
- .ret = -1,
- .err = EINVAL,
- },
- { // case04
- .ttype = NORMAL,
- .user = "nobody",
- .qname = QUEUE_NAME,
- .ret = -1,
- .err = EACCES,
- },
- { // case05
- .ttype = NORMAL,
- .qname = QUEUE_NAME,
- .oflag = O_CREAT | O_EXCL,
- .ret = -1,
- .err = EEXIST,
- },
- { // case06
- .ttype = NO_FILE,
- .qname = QUEUE_NAME,
- .oflag = O_CREAT,
- .ret = -1,
- .err = EMFILE,
- },
- { // case07
- .ttype = NORMAL,
- .qname = "/notexist",
- .oflag = 0,
- .ret = -1,
- .err = ENOENT,
- },
-
- { // case08
- .ttype = NO_SPACE,
- .user = "nobody",
- .qname = QUEUE_NAME,
- .oflag = O_CREAT,
- .ret = -1,
- .err = ENOSPC,
- },
-#endif
+ {
+ TYPE_NAME(NORMAL),
+ .qname = QUEUE_NAME,
+ .oflag = O_CREAT,
+ .rq = (struct mq_attr) {.mq_maxmsg = 20, .mq_msgsize = 16384},
+ .ret = 0,
+ .err = 0,
+ },
+ {
+ TYPE_NAME(NORMAL),
+ .qname = QUEUE_NAME,
+ .oflag = O_CREAT,
+ .ret = 0,
+ .err = 0,
+ },
+ {
+ TYPE_NAME(NORMAL),
+ .qname = "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaa",
+ .oflag = O_CREAT,
+ .ret = 0,
+ .err = 0,
+ },
+ {
+ TYPE_NAME(NORMAL),
+ .qname = "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaa",
+ .oflag = O_CREAT,
+ .ret = -1,
+ .err = ENAMETOOLONG,
+ },
+
+ {
+ TYPE_NAME(NORMAL),
+ .qname = "",
+ .oflag = O_CREAT,
+ .ret = -1,
+ .err = EINVAL,
+ },
+ {
+ TYPE_NAME(NORMAL),
+ .as_nobody = 1,
+ .qname = QUEUE_NAME,
+ .ret = -1,
+ .err = EACCES,
+ },
+ {
+ TYPE_NAME(NORMAL),
+ .qname = QUEUE_NAME,
+ .oflag = O_CREAT | O_EXCL,
+ .ret = -1,
+ .err = EEXIST,
+ },
+ {
+ TYPE_NAME(NO_FILE),
+ .qname = QUEUE_NAME,
+ .oflag = O_CREAT,
+ .ret = -1,
+ .err = EMFILE,
+ },
+ {
+ TYPE_NAME(NORMAL),
+ .qname = "/notexist",
+ .oflag = 0,
+ .ret = -1,
+ .err = ENOENT,
+ },
+ {
+ TYPE_NAME(NO_SPACE),
+ .as_nobody = 1,
+ .qname = QUEUE_NAME,
+ .oflag = O_CREAT,
+ .ret = -1,
+ .err = ENOSPC,
+ }
};
-/*
- * do_test()
- *
- * Input : TestCase Data
- * Return : RESULT_OK(0), RESULT_NG(1)
- *
- */
-
-static int do_test(struct test_case *tc)
+static void setup(void)
{
- int sys_ret;
- int sys_errno;
- int result = RESULT_OK;
- int rc, fd1 = -1, fd2 = -1, cmp_ok = 1;
- uid_t old_uid = -1;
- rlim_t oldlim = -1;
- int oldval = -1;
- struct mq_attr new, old, *p_attr;
-
- /*
- * When test ended with SIGTERM etc, mq descriptor is left remains.
- * So we delete it first.
- */
- TEST(mq_unlink(QUEUE_NAME));
+ euid = geteuid();
+ pw = SAFE_GETPWNAM("nobody");
+}
- /*
- * Execute system call
- */
+static void setup_n(unsigned int i)
+{
+ struct test_case *tc = &tcase[i];
- if (tc->ttype != NO_SPACE && !(tc->oflag & O_CREAT)) {
- errno = 0;
- TEST(sys_ret =
- mq_open(QUEUE_NAME, O_CREAT | O_EXCL | O_RDWR, S_IRWXU,
- NULL));
- sys_errno = errno;
- if (sys_ret < 0)
- goto TEST_END;
- fd1 = sys_ret;
- }
if (tc->ttype == NO_FILE) {
- TEST(rc = setup_ulimit_fnum(ULIMIT_FNUM, &oldlim));
- if (rc < 0) {
- result = 1;
- goto EXIT;
+ SAFE_GETRLIMIT(RLIMIT_NOFILE, &rlim);
+ if (rlim.rlim_cur > NOFILE_LIMIT) {
+ oldlim = rlim.rlim_cur;
+ rlim.rlim_cur = NOFILE_LIMIT;
+ SAFE_SETRLIMIT(RLIMIT_NOFILE, &rlim);
}
}
- /*
- * Change /proc/sys/fs/mqueue/queues_max
- */
if (tc->ttype == NO_SPACE) {
- TEST(rc = setup_proc_fs(PROC_MAX_QUEUES, 0, &oldval));
- if (rc < 0) {
- result = 1;
- goto EXIT;
- }
+ SAFE_FILE_SCANF(PROC_MAX_QUEUES, "%d", &max_queues);
+ SAFE_FILE_PRINTF(PROC_MAX_QUEUES, "%d", 0);
}
- /*
- * Change effective user id
- */
- if (tc->user != NULL) {
- TEST(rc = setup_euid(tc->user, &old_uid));
- if (rc < 0) {
- result = 1;
- goto EXIT;
- }
+ if (tc->as_nobody)
+ SAFE_SETEUID(pw->pw_uid);
+}
+
+static void cleanup(void)
+{
+ if (max_queues != -1 && FILE_PRINTF(PROC_MAX_QUEUES, "%d", max_queues))
+ tst_res(TWARN | TERRNO, "restoring max_queues back to %d failed",
+ max_queues);
+
+ if (fd1 > 0)
+ close(fd1);
+ if (fd2 > 0)
+ close(fd2);
+
+ mq_unlink(QUEUE_NAME);
+ if (strcmp(qname, QUEUE_NAME) != 0)
+ mq_unlink(qname);
+}
+
+static void cleanup_n(unsigned int i)
+{
+ struct test_case *tc = &tcase[i];
+
+ if (tc->as_nobody)
+ SAFE_SETEUID(euid);
+
+ if (oldlim != -1) {
+ rlim.rlim_cur = oldlim;
+ SAFE_SETRLIMIT(RLIMIT_NOFILE, &rlim);
}
+ if (fd1 > 0)
+ SAFE_CLOSE(fd1);
+ if (fd2 > 0)
+ SAFE_CLOSE(fd2);
+
+ cleanup();
+}
+
+static void do_test(unsigned int i)
+{
+ struct test_case *tc = &tcase[i];
+ struct mq_attr oldattr;
+
+ qname = tc->qname;
+ max_queues = oldlim = fd1 = fd2 = -1;
+
+ tst_res(TINFO, "queue name \"%s\"", qname);
+
/*
- * Execute system call
+ * When test ended with SIGTERM etc, mq descriptor is left remains.
+ * So we delete it first.
*/
- //tst_resm(TINFO,"PATH_MAX: %d\n", PATH_MAX);
- //tst_resm(TINFO,"NAME_MAX: %d", NAME_MAX);
- p_attr = NULL;
- if (tc->mq_maxmsg || tc->mq_msgsize) {
- new.mq_maxmsg = tc->mq_maxmsg;
- new.mq_msgsize = tc->mq_msgsize;
- p_attr = &new;
+ mq_unlink(QUEUE_NAME);
+
+ if (tc->ttype != NO_SPACE &&
+ (!(tc->oflag & O_CREAT) || tc->oflag & O_EXCL)) {
+ TEST(fd1 = mq_open(QUEUE_NAME, O_CREAT | O_EXCL | O_RDWR,
+ S_IRWXU, NULL));
+ if (fd1 < 0)
+ goto TEST_END;
}
- errno = 0;
+
+ setup_n(i);
+
if (tc->oflag & O_CREAT)
- TEST(sys_ret = mq_open(tc->qname, tc->oflag, S_IRWXU, p_attr));
+ TEST(fd2 = mq_open(qname, tc->oflag, S_IRWXU,
+ tc->rq.mq_maxmsg || tc->rq.mq_msgsize ? &tc->rq : NULL));
else
- TEST(sys_ret = mq_open(tc->qname, tc->oflag));
- sys_errno = errno;
- if (sys_ret < 0)
- goto TEST_END;
- fd2 = sys_ret;
-
- if (p_attr) {
- TEST(rc = ltp_syscall(__NR_mq_getsetattr, fd2, NULL, &old));
- if (TEST_RETURN < 0) {
- tst_resm(TFAIL,
- "mq_getsetattr failed - errno = %d : %s",
- TEST_ERRNO, strerror(TEST_ERRNO));
- result = 1;
- goto EXIT;
+ TEST(fd2 = mq_open(qname, tc->oflag));
+
+ if (fd2 > 0 && (tc->rq.mq_maxmsg || tc->rq.mq_msgsize)) {
+ if (mq_getattr(fd2, &oldattr) < 0) {
+ tst_res(TFAIL | TERRNO, "mq_getattr failed");
+ cleanup_n(i);
+ return;
+ }
+
+ if (oldattr.mq_maxmsg != tc->rq.mq_maxmsg
+ || oldattr.mq_msgsize != tc->rq.mq_msgsize) {
+ tst_res(TFAIL | TERRNO, "wrong mq_attr: "
+ "mq_maxmsg expected %ld return %ld, "
+ "mq_msgsize expected %ld return %ld",
+ tc->rq.mq_maxmsg, oldattr.mq_maxmsg, tc->rq.mq_msgsize,
+ oldattr.mq_msgsize);
+ cleanup_n(i);
+ return;
}
- tst_resm(TINFO, "mq_maxmsg E:%ld,\tR:%ld", new.mq_maxmsg,
- old.mq_maxmsg);
- tst_resm(TINFO, "mq_msgsize E:%ld,\tR:%ld", new.mq_msgsize,
- old.mq_msgsize);
- cmp_ok = old.mq_maxmsg == new.mq_maxmsg
- && old.mq_msgsize == new.mq_msgsize;
}
TEST_END:
- /*
- * Check results
- */
- result |= (sys_errno != tc->err) || !cmp_ok;
- PRINT_RESULT_CMP(sys_ret >= 0, tc->ret, tc->err, sys_ret, sys_errno,
- cmp_ok);
-
-EXIT:
- if (tc->user != NULL && old_uid != -1)
- TEST(cleanup_euid(old_uid));
-
- if (tc->ttype == NO_SPACE && oldval != -1)
- TEST(cleanup_proc_fs(PROC_MAX_QUEUES, oldval));
-
- if (tc->ttype == NO_FILE && oldlim != -1)
- TEST(cleanup_ulimit_fnum(oldlim));
- if (fd1 >= 0)
- TEST(close(fd1));
- if (fd2 >= 0)
- TEST(close(fd2));
- if (fd1 >= 0)
- TEST(mq_unlink(QUEUE_NAME));
- if (fd2 >= 0 && strcmp(tc->qname, QUEUE_NAME) != 0)
- TEST(mq_unlink(tc->qname));
-
- return result;
-}
-
-/*
- * main()
- */
-
-int main(int ac, char **av)
-{
- int result = RESULT_OK;
- int i;
- int lc;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); ++lc) {
- tst_count = 0;
- for (testno = 0; testno < TST_TOTAL; ++testno) {
-
- /*
- * Execute test
- */
- for (i = 0; i < (int)ARRAY_SIZE(tcase); i++) {
- int ret;
- tst_resm(TINFO, "(case%02d) START", i);
- ret = do_test(&tcase[i]);
- tst_resm(TINFO, "(case%02d) END => %s", i,
- (ret == 0) ? "OK" : "NG");
- result |= ret;
- }
-
- /*
- * Check results
- */
- switch (result) {
- case RESULT_OK:
- tst_resm(TPASS, "mq_open call succeeded ");
- break;
-
- default:
- tst_brkm(TFAIL | TTERRNO, cleanup,
- "mq_open failed");
- break;
- }
-
- }
+ if (TEST_ERRNO != tc->err || (tc->ret < 0 && TEST_RETURN != tc->ret) ||
+ (tc->ret >= 0 && TEST_RETURN < 0)) {
+ tst_res(TFAIL | TTERRNO, "%s returned: %ld, "
+ "expected: %d, expected errno: %s (%d)", tc->desc,
+ TEST_RETURN, tc->ret, tst_strerrno(tc->err), tc->err);
+ } else {
+ tst_res(TPASS | TTERRNO, "%s returned: %ld", tc->desc,
+ TEST_RETURN);
}
- cleanup();
- tst_exit();
+
+ cleanup_n(i);
}
+
+static struct tst_test test = {
+ .tid = "mq_open01",
+ .tcnt = ARRAY_SIZE(tcase),
+ .test = do_test,
+ .needs_root = 1,
+ .setup = setup,
+ .cleanup = cleanup,
+};
diff --git a/testcases/kernel/syscalls/utils/common_j_h.c b/testcases/kernel/syscalls/utils/common_j_h.c
index 43165ca20..dbdbc117a 100644
--- a/testcases/kernel/syscalls/utils/common_j_h.c
+++ b/testcases/kernel/syscalls/utils/common_j_h.c
@@ -227,113 +227,6 @@ int cleanup_swapfile(char *path)
return 0;
}
-/*
- * Change user limit that the calling process can open
- */
-int setup_ulimit_fnum(rlim_t newlim, rlim_t * oldlim)
-{
- int rc;
- struct rlimit rlim;
-
- rc = getrlimit(RLIMIT_NOFILE, &rlim);
- if (rc < 0) {
- EPRINTF("getrlimit failed.\n");
- return -1;
- }
- *oldlim = rlim.rlim_cur;
- if (newlim > rlim.rlim_max) {
- EPRINTF("can't set ulimit value: %ld.\n", newlim);
- return -1;
- }
- rlim.rlim_cur = newlim;
- rc = setrlimit(RLIMIT_NOFILE, &rlim);
- if (rc < 0) {
- EPRINTF("setrlimit failed.\n");
- return -1;
- }
- return 0;
-}
-
-int cleanup_ulimit_fnum(rlim_t oldlim)
-{
- int rc;
- struct rlimit rlim;
-
- rc = getrlimit(RLIMIT_NOFILE, &rlim);
- if (rc < 0) {
- EPRINTF("getrlimit failed.\n");
- return -1;
- }
- if (oldlim > rlim.rlim_max) {
- EPRINTF("can't set ulimit value: %ld.\n", oldlim);
- return -1;
- }
- rlim.rlim_cur = oldlim;
- rc = setrlimit(RLIMIT_NOFILE, &rlim);
- if (rc < 0) {
- EPRINTF("setrlimit failed.\n");
- return -1;
- }
- return 0;
-}
-
-/*
- * Change /proc or /sys setting
- */
-int setup_proc_fs(char *path, int newval, int *oldval)
-{
- int fd = -1, rc, len;
- char buf[32];
-
- fd = open(path, O_RDWR);
- if (fd < 0) {
- EPRINTF("open %s failed.\n", path);
- return -1;
- }
-
- do {
- rc = read(fd, buf, 32);
- } while (rc < 0 && errno == EAGAIN);
- if (rc < 0) {
- EPRINTF("read failed.\n");
- close(fd);
- return -1;
- }
-
- *oldval = atoi(buf);
- sprintf(buf, "%d\n", newval);
- len = strlen(buf);
- rc = write(fd, buf, len);
- close(fd);
- if (rc != len) {
- EPRINTF("write failed.\n");
- return -1;
- }
- return 0;
-}
-
-int cleanup_proc_fs(char *path, int oldval)
-{
- int fd = -1, rc, len;
- char buf[32];
-
- fd = open(path, O_RDWR);
- if (fd < 0) {
- EPRINTF("open %s failed.\n", path);
- return -1;
- }
-
- sprintf(buf, "%d\n", oldval);
- len = strlen(buf);
- rc = write(fd, buf, len);
- close(fd);
- if (rc != len) {
- EPRINTF("write failed.\n");
- return -1;
- }
- return 0;
-}
-
#if 0
/*
* Check max nodes from /sys/devices/system/node/node* files (for NUMA)
diff --git a/testcases/kernel/syscalls/utils/include_j_h.h b/testcases/kernel/syscalls/utils/include_j_h.h
index ff6aaf42d..742d96401 100644
--- a/testcases/kernel/syscalls/utils/include_j_h.h
+++ b/testcases/kernel/syscalls/utils/include_j_h.h
@@ -135,12 +135,6 @@ int cleanup_file(char *path);
int setup_swapfile(char *testdir, char *fname, char *path, size_t size);
int cleanup_swapfile(char *path);
-int setup_ulimit_fnum(rlim_t newlim, rlim_t *oldlim);
-int cleanup_ulimit_fnum(rlim_t oldlim);
-
-int setup_proc_fs(char *path, int newval, int *oldval);
-int cleanup_proc_fs(char *path, int oldval);
-
#define QUEUE_NAME "/test_mqueue"
pid_t create_echo_msg_proc(void);
--
2.11.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [LTP] [PATCH v3 2/2] syscalls/mq_open: fix old tests + convert to use new API
2016-12-10 20:29 ` [LTP] [PATCH v3 2/2] syscalls/mq_open: fix old tests + convert to use new API Petr Vorel
@ 2016-12-15 13:52 ` Cyril Hrubis
2016-12-15 14:34 ` Petr Vorel
0 siblings, 1 reply; 4+ messages in thread
From: Cyril Hrubis @ 2016-12-15 13:52 UTC (permalink / raw)
To: ltp
Hi!
> Hope it's not too complicated. cleanup(void) doesn't use any SAFE_* function, that's why they're two functions.
This version is better, but still more complicated than it could be.
> - /*
> - * Execute system call
> - */
> +static void setup_n(unsigned int i)
> +{
> + struct test_case *tc = &tcase[i];
>
> - if (tc->ttype != NO_SPACE && !(tc->oflag & O_CREAT)) {
> - errno = 0;
> - TEST(sys_ret =
> - mq_open(QUEUE_NAME, O_CREAT | O_EXCL | O_RDWR, S_IRWXU,
> - NULL));
> - sys_errno = errno;
> - if (sys_ret < 0)
> - goto TEST_END;
> - fd1 = sys_ret;
> - }
> if (tc->ttype == NO_FILE) {
> - TEST(rc = setup_ulimit_fnum(ULIMIT_FNUM, &oldlim));
> - if (rc < 0) {
> - result = 1;
> - goto EXIT;
> + SAFE_GETRLIMIT(RLIMIT_NOFILE, &rlim);
We can get the rlimit once in the test setup.
> + if (rlim.rlim_cur > NOFILE_LIMIT) {
> + oldlim = rlim.rlim_cur;
> + rlim.rlim_cur = NOFILE_LIMIT;
> + SAFE_SETRLIMIT(RLIMIT_NOFILE, &rlim);
> }
> }
>
> - /*
> - * Change /proc/sys/fs/mqueue/queues_max
> - */
> if (tc->ttype == NO_SPACE) {
> - TEST(rc = setup_proc_fs(PROC_MAX_QUEUES, 0, &oldval));
> - if (rc < 0) {
> - result = 1;
> - goto EXIT;
> - }
> + SAFE_FILE_SCANF(PROC_MAX_QUEUES, "%d", &max_queues);
Here as well, we can read the max_queues fil,e once in the test setup.
> + SAFE_FILE_PRINTF(PROC_MAX_QUEUES, "%d", 0);
> }
>
> - /*
> - * Change effective user id
> - */
> - if (tc->user != NULL) {
> - TEST(rc = setup_euid(tc->user, &old_uid));
> - if (rc < 0) {
> - result = 1;
> - goto EXIT;
> - }
> + if (tc->as_nobody)
> + SAFE_SETEUID(pw->pw_uid);
> +}
Looking at the code now, it may be clearer to add a setup() and
cleanup() function pointers to the test structure and split the
setup/cleanup per testcase so that we don't have to switch on tc->ttype.
> +static void cleanup(void)
> +{
> + if (max_queues != -1 && FILE_PRINTF(PROC_MAX_QUEUES, "%d", max_queues))
> + tst_res(TWARN | TERRNO, "restoring max_queues back to %d failed",
> + max_queues);
> +
> + if (fd1 > 0)
> + close(fd1);
> + if (fd2 > 0)
> + close(fd2);
> +
> + mq_unlink(QUEUE_NAME);
> + if (strcmp(qname, QUEUE_NAME) != 0)
> + mq_unlink(qname);
> +}
> +
> +static void cleanup_n(unsigned int i)
> +{
> + struct test_case *tc = &tcase[i];
> +
> + if (tc->as_nobody)
> + SAFE_SETEUID(euid);
> +
> + if (oldlim != -1) {
> + rlim.rlim_cur = oldlim;
> + SAFE_SETRLIMIT(RLIMIT_NOFILE, &rlim);
> }
>
> + if (fd1 > 0)
> + SAFE_CLOSE(fd1);
> + if (fd2 > 0)
> + SAFE_CLOSE(fd2);
> +
> + cleanup();
> +}
> +
> +static void do_test(unsigned int i)
> +{
> + struct test_case *tc = &tcase[i];
> + struct mq_attr oldattr;
> +
> + qname = tc->qname;
> + max_queues = oldlim = fd1 = fd2 = -1;
> +
> + tst_res(TINFO, "queue name \"%s\"", qname);
> +
> /*
> - * Execute system call
> + * When test ended with SIGTERM etc, mq descriptor is left remains.
> + * So we delete it first.
> */
> - //tst_resm(TINFO,"PATH_MAX: %d\n", PATH_MAX);
> - //tst_resm(TINFO,"NAME_MAX: %d", NAME_MAX);
> - p_attr = NULL;
> - if (tc->mq_maxmsg || tc->mq_msgsize) {
> - new.mq_maxmsg = tc->mq_maxmsg;
> - new.mq_msgsize = tc->mq_msgsize;
> - p_attr = &new;
> + mq_unlink(QUEUE_NAME);
> +
> + if (tc->ttype != NO_SPACE &&
> + (!(tc->oflag & O_CREAT) || tc->oflag & O_EXCL)) {
> + TEST(fd1 = mq_open(QUEUE_NAME, O_CREAT | O_EXCL | O_RDWR,
> + S_IRWXU, NULL));
> + if (fd1 < 0)
> + goto TEST_END;
> }
> +
> + setup_n(i);
> +
> if (tc->oflag & O_CREAT)
> - TEST(sys_ret = mq_open(tc->qname, tc->oflag, S_IRWXU, p_attr));
> + TEST(fd2 = mq_open(qname, tc->oflag, S_IRWXU,
> + tc->rq.mq_maxmsg || tc->rq.mq_msgsize ? &tc->rq : NULL));
I'm still puzzled by this part.
Why can't we just do setup() and cleanup() for each of the
testcases, instead of this trickery?
The first three testcases in struct testcase just need to unlink the
queue in the test specific cleanup.
The fourth and fift (ENAMETOOLONG and EINVAL) does not need any setup
nor cleanup.
The sixth (EACCESS) needs setup and cleanup with SAFE_SETEUID().
The seventh (EEXISTS) needs setup that creates the queue and cleanup
that unlinks it.
The eighth (EMFILE) needs setup and cleanup with setrlimit().
The tenth (ENOENT) does not need any setup nor cleanup.
The eleventh (ENOSPC) needs cleanup and setup that writes the file in /proc/sys/.
And the test function could just then be simple TEST(fd = mq_open(...))
and comparsion of the TEST_RETURN and TEST_ERRNO with the expected
return and errno.
Something as:
static void unlink_queue(void)
{
if (mq_unlink(QUEUE_NAME))
tst_brk(TBROK | TERRNO, "mq_unlink(" QUEUE_NAME ") failed");
}
static void create_queue(void)
{
if (mq_open(QUEUE_NAME, O_CREAT | O_EXCL | O_RDWR, S_IRWXU, NULL))
tst_brk(TBROK | TERRNO, "mq_open(" QUEUE_NAME ") failed");
}
static struct tcase {
char *qname,
int oflags,
struct mq_attr *attr,
int exp_ret,
int exp_errno,
void (*setup)(void),
void (*cleanup)(void),
} tcases[] = {
{
.qname = QUEUE_NAME,
.oflag = O_CREAT,
.exp_ret = 0,
.exp_errno = 0,
.cleanup = unlink_queue,
},
...
{
.qname = QUEUE_NAME
.oflag = O_CREAT | O_EXCL,
.exp_ret = -1,
.exp_errno = EEXIST,
.setup = create_queue,
.cleanup = unlink_queue,
}
};
static void do_test(unsigned int i)
{
struct tcase *tc = tcases[i];
if (tc->setup)
tc->setup();
TEST(mq_open(tc->qname, ...));
...
if (tc->cleanup)
tc->cleanup();
}
Or do I miss something and there is a reason why we can't write the test
this way?
--
Cyril Hrubis
chrubis@suse.cz
^ permalink raw reply [flat|nested] 4+ messages in thread
* [LTP] [PATCH v3 2/2] syscalls/mq_open: fix old tests + convert to use new API
2016-12-15 13:52 ` Cyril Hrubis
@ 2016-12-15 14:34 ` Petr Vorel
0 siblings, 0 replies; 4+ messages in thread
From: Petr Vorel @ 2016-12-15 14:34 UTC (permalink / raw)
To: ltp
Hi Cyril!
Thank you for your review, ideas, examples!
> > + SAFE_GETRLIMIT(RLIMIT_NOFILE, &rlim);
> We can get the rlimit once in the test setup.
> > + SAFE_FILE_SCANF(PROC_MAX_QUEUES, "%d", &max_queues);
> Here as well, we can read the max_queues fil,e once in the test setup.
I thought it would be safer to read it before test to get actual value. I still think too
complicatedly about tests :-(.
> Why can't we just do setup() and cleanup() for each of the
> testcases, instead of this trickery?
I didn't like it either, I just didn't come up with simple function pointer idea.
> Or do I miss something and there is a reason why we can't write the test
> this way?
No you don't, I just haven't achieved the zen of programming yet :-(. How nice and simple,
I'll use it.
Kind regards,
Petr
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.linux.it/pipermail/ltp/attachments/20161215/543a0c85/attachment.sig>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2016-12-15 14:34 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-12-10 20:29 [LTP] [PATCH v3 1/2] lib: add FILE_PRINTF Petr Vorel
2016-12-10 20:29 ` [LTP] [PATCH v3 2/2] syscalls/mq_open: fix old tests + convert to use new API Petr Vorel
2016-12-15 13:52 ` Cyril Hrubis
2016-12-15 14:34 ` Petr Vorel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox