* [LTP] [PATCH] linkat01: Split into 2 cases and convert to new API
@ 2024-03-25 6:01 Yang Xu via ltp
2024-07-17 11:43 ` Cyril Hrubis
0 siblings, 1 reply; 2+ messages in thread
From: Yang Xu via ltp @ 2024-03-25 6:01 UTC (permalink / raw)
To: ltp
Currently linkat01 includes both positive cases and failure cases. The logic
contains many if-else statement and is a little complex.
Now linkat01 will be split into 2 cases: linkat01 and linkat03. The positive
cases remain in linkat01 case, and failure cases move to linkat03 case. With
new api TST_EXP_PASS() and TST_EXP_FAIL(), the logic is also simplified.
Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/linkat/.gitignore | 1 +
testcases/kernel/syscalls/linkat/linkat01.c | 385 ++++++--------------
testcases/kernel/syscalls/linkat/linkat03.c | 120 ++++++
4 files changed, 240 insertions(+), 267 deletions(-)
create mode 100644 testcases/kernel/syscalls/linkat/linkat03.c
diff --git a/runtest/syscalls b/runtest/syscalls
index 4ed2b5602..771d654c8 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -701,6 +701,7 @@ link08 link08
#linkat test cases
linkat01 linkat01
linkat02 linkat02
+linkat03 linkat03
listen01 listen01
diff --git a/testcases/kernel/syscalls/linkat/.gitignore b/testcases/kernel/syscalls/linkat/.gitignore
index 1b307c9df..52b019e25 100644
--- a/testcases/kernel/syscalls/linkat/.gitignore
+++ b/testcases/kernel/syscalls/linkat/.gitignore
@@ -1,2 +1,3 @@
/linkat01
/linkat02
+/linkat03
diff --git a/testcases/kernel/syscalls/linkat/linkat01.c b/testcases/kernel/syscalls/linkat/linkat01.c
index 57cfbcfc6..1e77898d6 100644
--- a/testcases/kernel/syscalls/linkat/linkat01.c
+++ b/testcases/kernel/syscalls/linkat/linkat01.c
@@ -1,93 +1,44 @@
-/******************************************************************************
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ * Copyright (c) Linux Test Project, 2006-2024
+ */
+
+/*\
+ * [Description]
*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * 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
- *
- * NAME
- * linkat01.c
- *
- * DESCRIPTION
- * This test case will verify basic function of linkat
- * added by kernel 2.6.16 or up.
- *
- * USAGE: <for command-line>
- * linkat01 [-c n] [-e] [-i n] [-I x] [-P x] [-t] [-p]
- * where:
- * -c n : Run n copies simultaneously.
- * -e : Turn on errno logging.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -p : Pause for SIGUSR1 before starting
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * Author
- * Yi Yang <yyangcdl@cn.ibm.com>
- *
- * History
- * 08/25/2006 Created first by Yi Yang <yyangcdl@cn.ibm.com>
- *
- *****************************************************************************/
+ * Check the basic function of linkat that normally returns.
+ */
#define _GNU_SOURCE
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <fcntl.h>
-#include <unistd.h>
#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <inttypes.h>
-#include <limits.h>
-#include "test.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "tst_test.h"
+#include "tst_safe_macros.h"
#include "lapi/syscalls.h"
-#include "safe_macros.h"
-
-#ifndef AT_FDCWD
-#define AT_FDCWD -100
-#endif
-#ifndef AT_SYMLINK_FOLLOW
-#define AT_SYMLINK_FOLLOW 0x400
-#endif
-
-struct test_struct;
-static void setup();
-static void cleanup();
-static void setup_every_copy();
-static void mylinkat_test(struct test_struct *desc);
+#include "lapi/fcntl.h"
#define TEST_DIR1 "olddir"
#define TEST_DIR2 "newdir"
#define TEST_DIR3 "deldir"
#define TEST_FILE1 "oldfile"
-#define TEST_FILE2 "newfile"
-#define TEST_FIFO "fifo"
-#define DPATHNAME_FMT "%s/" TEST_DIR2 "/" TEST_FILE1
-#define SPATHNAME_FMT "%s/" TEST_DIR1 "/" TEST_FILE1
+#define DPATHNAME_FMT "%s/" TEST_DIR2 "/" TEST_FILE1
+#define SPATHNAME_FMT "%s/" TEST_DIR1 "/" TEST_FILE1
static char dpathname[PATH_MAX];
static char spathname[PATH_MAX];
-static int olddirfd, newdirfd = -1, cwd_fd = AT_FDCWD, stdinfd = 0, badfd =
- -1, deldirfd;
-
-struct test_struct {
+static int olddirfd;
+static int newdirfd = -1;
+static int cwd_fd = AT_FDCWD;
+static int stdinfd;
+static int badfd = -1;
+static int deldirfd;
+
+static struct tcase {
int *oldfd;
const char *oldfn;
int *newfd;
@@ -95,222 +46,122 @@ struct test_struct {
int flags;
const char *referencefn1;
const char *referencefn2;
- int expected_errno;
-} test_desc[] = {
+} tcases[] = {
/* 1. relative paths */
- {
- &olddirfd, TEST_FILE1, &newdirfd, TEST_FILE1, 0,
- TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0},
- /* 2. abs path at source */
- {
- &olddirfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0, 0},
- /* 3. abs path at dst */
- {
- &olddirfd, TEST_FILE1, &newdirfd, dpathname, 0,
- TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0},
- /* 4. relative paths to cwd */
- {
- &cwd_fd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0,
- TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0},
- /* 5. relative paths to cwd */
- {
- &olddirfd, TEST_FILE1, &cwd_fd, TEST_DIR2 "/" TEST_FILE1, 0,
- TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0},
- /* 6. abs path at source */
- {
- &cwd_fd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0, 0},
- /* 7. abs path at dst */
- {
- &olddirfd, TEST_FILE1, &cwd_fd, dpathname, 0,
- TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0},
- /* 8. relative paths to invalid */
- {
- &stdinfd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0,
- 0, 0, ENOTDIR},
- /* 9. relative paths to invalid */
- {
- &olddirfd, TEST_FILE1, &stdinfd, TEST_DIR2 "/" TEST_FILE1, 0,
- 0, 0, ENOTDIR},
- /* 10. abs path at source */
- {
- &stdinfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0, 0},
- /* 11. abs path at dst */
- {
- &olddirfd, TEST_FILE1, &stdinfd, dpathname, 0,
- TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0},
- /* 12. relative paths to bad */
- {
- &badfd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0,
- 0, 0, EBADF},
- /* 13. relative paths to bad */
- {
- &olddirfd, TEST_FILE1, &badfd, TEST_DIR2 "/" TEST_FILE1, 0,
- 0, 0, EBADF},
- /* 14. abs path at source */
- {
- &badfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0, 0},
- /* 15. abs path at dst */
- {
- &olddirfd, TEST_FILE1, &badfd, dpathname, 0,
- TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0},
- /* 16. relative paths to deleted */
- {
- &deldirfd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0,
- 0, 0, ENOENT},
- /* 17. relative paths to deleted */
- {
- &olddirfd, TEST_FILE1, &deldirfd, TEST_DIR2 "/" TEST_FILE1, 0,
- 0, 0, ENOENT},
- /* 18. abs path at source */
- {
- &deldirfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0, 0},
- /* 19. abs path at dst */
- {
- &olddirfd, TEST_FILE1, &deldirfd, dpathname, 0,
- TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0},
- /* 20. x-device link */
- {
- &cwd_fd, "/proc/cpuinfo", &newdirfd, TEST_FILE1, 0, 0, 0, EXDEV},
- /* 21. directory link */
- {
- &olddirfd, ".", &newdirfd, TEST_FILE1, 0, 0, 0, EPERM},
- /* 22. invalid flag */
- {
- &olddirfd, TEST_FILE1, &newdirfd, TEST_FILE1, 1, 0, 0, EINVAL},
- /* 23. fifo link */
- /* XXX (garrcoop): Removed because it hangs the overall test. Need to
- * find a legitimate means to exercise this functionality, if in fact
- * it's a valid testcase -- which it should be.
- */
- /* { &olddirfd, TEST_FIFO, &newdirfd, TEST_FILE1, 0,
- TEST_DIR1"/"TEST_FIFO, TEST_DIR2"/"TEST_FILE1, 0 } */
+ {&olddirfd, TEST_FILE1, &newdirfd, TEST_FILE1, 0,
+ TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1},
+ /* 2. absolution path at source */
+ {&olddirfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0},
+ /* 3. absolution path at destination */
+ {&olddirfd, TEST_FILE1, &newdirfd, dpathname, 0,
+ TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1},
+ /* 4. relative paths to cwd */
+ {&cwd_fd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0,
+ TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1},
+ /* 5. cwd to relative paths */
+ {&olddirfd, TEST_FILE1, &cwd_fd, TEST_DIR2 "/" TEST_FILE1, 0,
+ TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1},
+ /* 6. cwd to absolution paths */
+ {&cwd_fd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0},
+ /* 7. absolution paths to cwd */
+ {&olddirfd, TEST_FILE1, &cwd_fd, dpathname, 0,
+ TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1},
+ /* 8. invalid directory to absolution paths */
+ {&stdinfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0},
+ /* 9. absolution paths to invalid directory */
+ {&olddirfd, TEST_FILE1, &stdinfd, dpathname, 0,
+ TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1},
+ /* 10. bad fd to absolution paths */
+ {&badfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0},
+ /* 11. absolution paths to bad fd */
+ {&olddirfd, TEST_FILE1, &badfd, dpathname, 0,
+ TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1},
+ /* 12. deleted to absolution paths */
+ {&deldirfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0},
+ /* 13. absolution paths to deleted */
+ {&olddirfd, TEST_FILE1, &deldirfd, dpathname, 0,
+ TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1},
};
-char *TCID = "linkat01";
-int TST_TOTAL = sizeof(test_desc) / sizeof(*test_desc);
-
-static int mylinkat(int olddirfd, const char *oldfilename, int newdirfd,
- const char *newfilename, int flags)
+static void setup(void)
{
- return tst_syscall(__NR_linkat, olddirfd, oldfilename, newdirfd,
- newfilename, flags);
-}
-
-int main(int ac, char **av)
-{
- int lc;
- int i;
-
- tst_parse_opts(ac, av, NULL, NULL);
-
- setup();
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
+ char *cwd;
+ int fd;
- tst_count = 0;
+ cwd = get_current_dir_name();
+ if (cwd == NULL) {
+ tst_brk(TFAIL | TERRNO,
+ "Failed to get current working directory.");
+ }
- for (i = 0; i < TST_TOTAL; i++) {
- setup_every_copy();
- mylinkat_test(&test_desc[i]);
- }
+ SAFE_MKDIR(TEST_DIR1, 0700);
+ SAFE_MKDIR(TEST_DIR3, 0700);
+ olddirfd = SAFE_OPEN(TEST_DIR1, O_DIRECTORY);
+ deldirfd = SAFE_OPEN(TEST_DIR3, O_DIRECTORY);
+ fd = SAFE_OPEN(TEST_DIR1 "/" TEST_FILE1, O_CREAT | O_EXCL, 0600);
+ SAFE_CLOSE(fd);
- }
+ snprintf(dpathname, sizeof(dpathname), DPATHNAME_FMT, cwd);
+ snprintf(spathname, sizeof(spathname), SPATHNAME_FMT, cwd);
- cleanup();
- tst_exit();
+ free(cwd);
}
-static void setup_every_copy(void)
+static void setup_every_case(void)
{
close(newdirfd);
unlink(dpathname);
rmdir(TEST_DIR2);
- SAFE_MKDIR(cleanup, TEST_DIR2, 0700);
- newdirfd = SAFE_OPEN(cleanup, TEST_DIR2, O_DIRECTORY);
+ SAFE_MKDIR(TEST_DIR2, 0700);
+ newdirfd = SAFE_OPEN(TEST_DIR2, O_DIRECTORY);
}
-static void mylinkat_test(struct test_struct *desc)
+static void verify_linkat(unsigned int i)
{
- int fd;
-
- TEST(mylinkat
- (*desc->oldfd, desc->oldfn, *desc->newfd, desc->newfn,
- desc->flags));
-
- if (TEST_ERRNO == desc->expected_errno) {
- if (TEST_RETURN == 0 && desc->referencefn1 != NULL) {
- int tnum = rand(), vnum = ~tnum;
- fd = SAFE_OPEN(cleanup, desc->referencefn1,
- O_RDWR);
- SAFE_WRITE(cleanup, SAFE_WRITE_ALL, fd, &tnum,
- sizeof(tnum));
- SAFE_CLOSE(cleanup, fd);
+ struct tcase *tc = &tcases[i];
- fd = SAFE_OPEN(cleanup, desc->referencefn2,
- O_RDONLY);
- SAFE_READ(cleanup, 1, fd, &vnum, sizeof(vnum));
- SAFE_CLOSE(cleanup, fd);
+ int fd;
- if (tnum == vnum)
- tst_resm(TPASS,
- "linkat is functionality correct");
- else {
- tst_resm(TFAIL,
- "The link file's content isn't "
- "as same as the original file's "
- "although linkat returned 0");
+ setup_every_case();
+
+ if (tc->referencefn1 != NULL) {
+ TST_EXP_PASS_SILENT(linkat(*tc->oldfd, tc->oldfn,
+ *tc->newfd, tc->newfn, tc->flags));
+ if (TST_PASS) {
+ int tnum = rand();
+ int vnum = ~tnum;
+
+ fd = SAFE_OPEN(tc->referencefn1, O_RDWR);
+ SAFE_WRITE(SAFE_WRITE_ALL, fd, &tnum, sizeof(tnum));
+ SAFE_CLOSE(fd);
+
+ fd = SAFE_OPEN(tc->referencefn2, O_RDONLY);
+ SAFE_READ(1, fd, &vnum, sizeof(vnum));
+ SAFE_CLOSE(fd);
+
+ if (tnum == vnum) {
+ tst_res(TPASS,
+ "linkat is functionality correct");
+ } else {
+ tst_res(TFAIL,
+ "The link file's content isn't "
+ "as same as the original file's "
+ "although linkat returned 0");
}
} else {
- if (TEST_RETURN == 0)
- tst_resm(TPASS,
- "linkat succeeded as expected");
- else
- tst_resm(TPASS | TTERRNO,
- "linkat failed as expected");
+ tst_res(TFAIL, "linkat failed");
}
} else {
- if (TEST_RETURN == 0)
- tst_resm(TFAIL, "linkat succeeded unexpectedly");
- else
- tst_resm(TFAIL | TTERRNO,
- "linkat failed unexpectedly; expected %d - %s",
- desc->expected_errno,
- strerror(desc->expected_errno));
- }
-}
-
-void setup(void)
-{
- char *cwd;
- int fd;
-
- tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
- tst_tmpdir();
-
- cwd = get_current_dir_name();
- if (cwd == NULL) {
- tst_brkm(TFAIL | TERRNO, cleanup,
- "Failed to get current working directory");
+ TST_EXP_PASS(linkat(*tc->oldfd, tc->oldfn,
+ *tc->newfd, tc->newfn, tc->flags),
+ "linkat");
}
-
- SAFE_MKDIR(cleanup, TEST_DIR1, 0700);
- SAFE_MKDIR(cleanup, TEST_DIR3, 0700);
- olddirfd = SAFE_OPEN(cleanup, TEST_DIR1, O_DIRECTORY);
- deldirfd = SAFE_OPEN(cleanup, TEST_DIR3, O_DIRECTORY);
- SAFE_RMDIR(cleanup, TEST_DIR3);
- fd = SAFE_OPEN(cleanup, TEST_DIR1 "/" TEST_FILE1, O_CREAT | O_EXCL, 0600);
- SAFE_CLOSE(cleanup, fd);
- SAFE_MKFIFO(cleanup, TEST_DIR1 "/" TEST_FIFO, 0600);
-
- snprintf(dpathname, sizeof(dpathname), DPATHNAME_FMT, cwd);
- snprintf(spathname, sizeof(spathname), SPATHNAME_FMT, cwd);
-
- free(cwd);
}
-static void cleanup(void)
-{
- tst_rmdir();
-}
+static struct tst_test test = {
+ .tcnt = ARRAY_SIZE(tcases),
+ .setup = setup,
+ .test = verify_linkat,
+ .needs_tmpdir = 1,
+};
diff --git a/testcases/kernel/syscalls/linkat/linkat03.c b/testcases/kernel/syscalls/linkat/linkat03.c
new file mode 100644
index 000000000..4ee25106e
--- /dev/null
+++ b/testcases/kernel/syscalls/linkat/linkat03.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ * Copyright (c) Linux Test Project, 2006-2024
+ */
+
+/*\
+ * [Description]
+ *
+ * Check the basic function of linkat that returns error.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+#include "lapi/syscalls.h"
+#include "lapi/fcntl.h"
+
+#define TEST_DIR1 "olddir"
+#define TEST_DIR2 "newdir"
+#define TEST_DIR3 "deldir"
+#define TEST_FILE1 "oldfile"
+
+static int olddirfd;
+static int newdirfd = -1;
+static int cwd_fd = AT_FDCWD;
+static int stdinfd;
+static int badfd = -1;
+static int deldirfd;
+
+static struct tcase {
+ int *oldfd;
+ const char *oldfn;
+ int *newfd;
+ const char *newfn;
+ int flags;
+ const char *referencefn1;
+ const char *referencefn2;
+ int expected_errno;
+} tcases[] = {
+ /* 1. invalid directory to relative paths */
+ {&stdinfd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0,
+ 0, 0, ENOTDIR},
+ /* 2. relative paths to invalid directory */
+ {&olddirfd, TEST_FILE1, &stdinfd, TEST_DIR2 "/" TEST_FILE1, 0,
+ 0, 0, ENOTDIR},
+ /* 3. bad fd to relative paths */
+ {&badfd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0,
+ 0, 0, EBADF},
+ /* 4. relative paths to bad fd */
+ {&olddirfd, TEST_FILE1, &badfd, TEST_DIR2 "/" TEST_FILE1, 0,
+ 0, 0, EBADF},
+ /* 5. deleted to relative paths */
+ {&deldirfd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0,
+ 0, 0, ENOENT},
+ /* 6. relative paths to deleted */
+ {&olddirfd, TEST_FILE1, &deldirfd, TEST_DIR2 "/" TEST_FILE1, 0,
+ 0, 0, ENOENT},
+ /* 7. x-device link */
+ {&cwd_fd, "/proc/cpuinfo", &newdirfd, TEST_FILE1, 0, 0, 0, EXDEV},
+ /* 8. directory link */
+ {&olddirfd, ".", &newdirfd, TEST_FILE1, 0, 0, 0, EPERM},
+ /* 9. invalid flag */
+ {&olddirfd, TEST_FILE1, &newdirfd, TEST_FILE1, 1, 0, 0, EINVAL},
+};
+
+static void setup(void)
+{
+ char *cwd;
+ int fd;
+
+ cwd = get_current_dir_name();
+ if (cwd == NULL) {
+ tst_brk(TFAIL | TERRNO,
+ "Failed to get current working directory.");
+ }
+
+ SAFE_MKDIR(TEST_DIR1, 0700);
+ SAFE_MKDIR(TEST_DIR3, 0700);
+ olddirfd = SAFE_OPEN(TEST_DIR1, O_DIRECTORY);
+ deldirfd = SAFE_OPEN(TEST_DIR3, O_DIRECTORY);
+ SAFE_RMDIR(TEST_DIR3);
+ fd = SAFE_OPEN(TEST_DIR1 "/" TEST_FILE1, O_CREAT | O_EXCL, 0600);
+ SAFE_CLOSE(fd);
+
+ free(cwd);
+}
+
+static void setup_every_case(void)
+{
+ close(newdirfd);
+ rmdir(TEST_DIR2);
+
+ SAFE_MKDIR(TEST_DIR2, 0700);
+ newdirfd = SAFE_OPEN(TEST_DIR2, O_DIRECTORY);
+}
+
+static void verify_linkat(unsigned int i)
+{
+ struct tcase *tc = &tcases[i];
+
+ setup_every_case();
+
+ TST_EXP_FAIL(linkat(*tc->oldfd, tc->oldfn, *tc->newfd,
+ tc->newfn, tc->flags),
+ tc->expected_errno,
+ "linkat failed as expected");
+}
+
+static struct tst_test test = {
+ .tcnt = ARRAY_SIZE(tcases),
+ .setup = setup,
+ .test = verify_linkat,
+ .needs_tmpdir = 1,
+};
--
2.39.3
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [LTP] [PATCH] linkat01: Split into 2 cases and convert to new API
2024-03-25 6:01 [LTP] [PATCH] linkat01: Split into 2 cases and convert to new API Yang Xu via ltp
@ 2024-07-17 11:43 ` Cyril Hrubis
0 siblings, 0 replies; 2+ messages in thread
From: Cyril Hrubis @ 2024-07-17 11:43 UTC (permalink / raw)
To: Yang Xu; +Cc: ltp
Hi!
> #define TEST_DIR1 "olddir"
> #define TEST_DIR2 "newdir"
> #define TEST_DIR3 "deldir"
> #define TEST_FILE1 "oldfile"
> -#define TEST_FILE2 "newfile"
> -#define TEST_FIFO "fifo"
>
> -#define DPATHNAME_FMT "%s/" TEST_DIR2 "/" TEST_FILE1
> -#define SPATHNAME_FMT "%s/" TEST_DIR1 "/" TEST_FILE1
> +#define DPATHNAME_FMT "%s/" TEST_DIR2 "/" TEST_FILE1
> +#define SPATHNAME_FMT "%s/" TEST_DIR1 "/" TEST_FILE1
>
> static char dpathname[PATH_MAX];
> static char spathname[PATH_MAX];
> -static int olddirfd, newdirfd = -1, cwd_fd = AT_FDCWD, stdinfd = 0, badfd =
> - -1, deldirfd;
> -
> -struct test_struct {
> +static int olddirfd;
> +static int newdirfd = -1;
> +static int cwd_fd = AT_FDCWD;
> +static int stdinfd;
> +static int badfd = -1;
> +static int deldirfd;
> +
> +static struct tcase {
> int *oldfd;
> const char *oldfn;
> int *newfd;
> @@ -95,222 +46,122 @@ struct test_struct {
> int flags;
> const char *referencefn1;
> const char *referencefn2;
These two should better be named:
const char *filename;
const char *linkname;
So that it's clear where they point to.
Moreover the actual paths seems to be the same for all testcases, so I
suppose that we can just define two macros instead as:
#define FILENAME TEST_DIR1 "/" TEST_FILE1
#define LINKNAME TEST_DIR2 "/" TEST_FILE1
And remove these two members from the structure.
> - int expected_errno;
> -} test_desc[] = {
> +} tcases[] = {
> /* 1. relative paths */
> - {
> - &olddirfd, TEST_FILE1, &newdirfd, TEST_FILE1, 0,
> - TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0},
> - /* 2. abs path at source */
> - {
> - &olddirfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0, 0},
> - /* 3. abs path at dst */
> - {
> - &olddirfd, TEST_FILE1, &newdirfd, dpathname, 0,
> - TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0},
> - /* 4. relative paths to cwd */
> - {
> - &cwd_fd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0,
> - TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0},
> - /* 5. relative paths to cwd */
> - {
> - &olddirfd, TEST_FILE1, &cwd_fd, TEST_DIR2 "/" TEST_FILE1, 0,
> - TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0},
> - /* 6. abs path at source */
> - {
> - &cwd_fd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0, 0},
> - /* 7. abs path at dst */
> - {
> - &olddirfd, TEST_FILE1, &cwd_fd, dpathname, 0,
> - TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0},
> - /* 8. relative paths to invalid */
> - {
> - &stdinfd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0,
> - 0, 0, ENOTDIR},
> - /* 9. relative paths to invalid */
> - {
> - &olddirfd, TEST_FILE1, &stdinfd, TEST_DIR2 "/" TEST_FILE1, 0,
> - 0, 0, ENOTDIR},
> - /* 10. abs path at source */
> - {
> - &stdinfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0, 0},
> - /* 11. abs path at dst */
> - {
> - &olddirfd, TEST_FILE1, &stdinfd, dpathname, 0,
> - TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0},
> - /* 12. relative paths to bad */
> - {
> - &badfd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0,
> - 0, 0, EBADF},
> - /* 13. relative paths to bad */
> - {
> - &olddirfd, TEST_FILE1, &badfd, TEST_DIR2 "/" TEST_FILE1, 0,
> - 0, 0, EBADF},
> - /* 14. abs path at source */
> - {
> - &badfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0, 0},
> - /* 15. abs path at dst */
> - {
> - &olddirfd, TEST_FILE1, &badfd, dpathname, 0,
> - TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0},
> - /* 16. relative paths to deleted */
> - {
> - &deldirfd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0,
> - 0, 0, ENOENT},
> - /* 17. relative paths to deleted */
> - {
> - &olddirfd, TEST_FILE1, &deldirfd, TEST_DIR2 "/" TEST_FILE1, 0,
> - 0, 0, ENOENT},
> - /* 18. abs path at source */
> - {
> - &deldirfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0, 0},
> - /* 19. abs path at dst */
> - {
> - &olddirfd, TEST_FILE1, &deldirfd, dpathname, 0,
> - TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0},
> - /* 20. x-device link */
> - {
> - &cwd_fd, "/proc/cpuinfo", &newdirfd, TEST_FILE1, 0, 0, 0, EXDEV},
> - /* 21. directory link */
> - {
> - &olddirfd, ".", &newdirfd, TEST_FILE1, 0, 0, 0, EPERM},
> - /* 22. invalid flag */
> - {
> - &olddirfd, TEST_FILE1, &newdirfd, TEST_FILE1, 1, 0, 0, EINVAL},
> - /* 23. fifo link */
> - /* XXX (garrcoop): Removed because it hangs the overall test. Need to
> - * find a legitimate means to exercise this functionality, if in fact
> - * it's a valid testcase -- which it should be.
> - */
> - /* { &olddirfd, TEST_FIFO, &newdirfd, TEST_FILE1, 0,
> - TEST_DIR1"/"TEST_FIFO, TEST_DIR2"/"TEST_FILE1, 0 } */
> + {&olddirfd, TEST_FILE1, &newdirfd, TEST_FILE1, 0,
> + TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1},
> + /* 2. absolution path at source */
> + {&olddirfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0},
> + /* 3. absolution path at destination */
> + {&olddirfd, TEST_FILE1, &newdirfd, dpathname, 0,
> + TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1},
> + /* 4. relative paths to cwd */
> + {&cwd_fd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0,
> + TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1},
> + /* 5. cwd to relative paths */
> + {&olddirfd, TEST_FILE1, &cwd_fd, TEST_DIR2 "/" TEST_FILE1, 0,
> + TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1},
> + /* 6. cwd to absolution paths */
> + {&cwd_fd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0},
> + /* 7. absolution paths to cwd */
> + {&olddirfd, TEST_FILE1, &cwd_fd, dpathname, 0,
> + TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1},
> + /* 8. invalid directory to absolution paths */
> + {&stdinfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0},
> + /* 9. absolution paths to invalid directory */
> + {&olddirfd, TEST_FILE1, &stdinfd, dpathname, 0,
> + TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1},
> + /* 10. bad fd to absolution paths */
> + {&badfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0},
> + /* 11. absolution paths to bad fd */
> + {&olddirfd, TEST_FILE1, &badfd, dpathname, 0,
> + TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1},
> + /* 12. deleted to absolution paths */
> + {&deldirfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0},
> + /* 13. absolution paths to deleted */
> + {&olddirfd, TEST_FILE1, &deldirfd, dpathname, 0,
> + TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1},
> };
>
> -char *TCID = "linkat01";
> -int TST_TOTAL = sizeof(test_desc) / sizeof(*test_desc);
> -
> -static int mylinkat(int olddirfd, const char *oldfilename, int newdirfd,
> - const char *newfilename, int flags)
> +static void setup(void)
> {
> - return tst_syscall(__NR_linkat, olddirfd, oldfilename, newdirfd,
> - newfilename, flags);
> -}
> -
> -int main(int ac, char **av)
> -{
> - int lc;
> - int i;
> -
> - tst_parse_opts(ac, av, NULL, NULL);
> -
> - setup();
> -
> - for (lc = 0; TEST_LOOPING(lc); lc++) {
> + char *cwd;
> + int fd;
>
> - tst_count = 0;
> + cwd = get_current_dir_name();
> + if (cwd == NULL) {
> + tst_brk(TFAIL | TERRNO,
> + "Failed to get current working directory.");
> + }
>
> - for (i = 0; i < TST_TOTAL; i++) {
> - setup_every_copy();
> - mylinkat_test(&test_desc[i]);
> - }
> + SAFE_MKDIR(TEST_DIR1, 0700);
> + SAFE_MKDIR(TEST_DIR3, 0700);
> + olddirfd = SAFE_OPEN(TEST_DIR1, O_DIRECTORY);
> + deldirfd = SAFE_OPEN(TEST_DIR3, O_DIRECTORY);
> + fd = SAFE_OPEN(TEST_DIR1 "/" TEST_FILE1, O_CREAT | O_EXCL, 0600);
> + SAFE_CLOSE(fd);
>
> - }
> + snprintf(dpathname, sizeof(dpathname), DPATHNAME_FMT, cwd);
> + snprintf(spathname, sizeof(spathname), SPATHNAME_FMT, cwd);
>
> - cleanup();
> - tst_exit();
> + free(cwd);
> }
>
> -static void setup_every_copy(void)
> +static void setup_every_case(void)
> {
> close(newdirfd);
> unlink(dpathname);
> rmdir(TEST_DIR2);
>
> - SAFE_MKDIR(cleanup, TEST_DIR2, 0700);
> - newdirfd = SAFE_OPEN(cleanup, TEST_DIR2, O_DIRECTORY);
> + SAFE_MKDIR(TEST_DIR2, 0700);
> + newdirfd = SAFE_OPEN(TEST_DIR2, O_DIRECTORY);
As far as I can tell the only thing that needs to be done on each
iteration is the unlink of dpathname. The rest could be moved into the
test setup.
> }
>
> -static void mylinkat_test(struct test_struct *desc)
> +static void verify_linkat(unsigned int i)
> {
> - int fd;
> -
> - TEST(mylinkat
> - (*desc->oldfd, desc->oldfn, *desc->newfd, desc->newfn,
> - desc->flags));
> -
> - if (TEST_ERRNO == desc->expected_errno) {
> - if (TEST_RETURN == 0 && desc->referencefn1 != NULL) {
> - int tnum = rand(), vnum = ~tnum;
> - fd = SAFE_OPEN(cleanup, desc->referencefn1,
> - O_RDWR);
> - SAFE_WRITE(cleanup, SAFE_WRITE_ALL, fd, &tnum,
> - sizeof(tnum));
> - SAFE_CLOSE(cleanup, fd);
> + struct tcase *tc = &tcases[i];
>
> - fd = SAFE_OPEN(cleanup, desc->referencefn2,
> - O_RDONLY);
> - SAFE_READ(cleanup, 1, fd, &vnum, sizeof(vnum));
> - SAFE_CLOSE(cleanup, fd);
> + int fd;
>
> - if (tnum == vnum)
> - tst_resm(TPASS,
> - "linkat is functionality correct");
> - else {
> - tst_resm(TFAIL,
> - "The link file's content isn't "
> - "as same as the original file's "
> - "although linkat returned 0");
> + setup_every_case();
> +
> + if (tc->referencefn1 != NULL) {
> + TST_EXP_PASS_SILENT(linkat(*tc->oldfd, tc->oldfn,
> + *tc->newfd, tc->newfn, tc->flags));
> + if (TST_PASS) {
> + int tnum = rand();
> + int vnum = ~tnum;
> +
> + fd = SAFE_OPEN(tc->referencefn1, O_RDWR);
> + SAFE_WRITE(SAFE_WRITE_ALL, fd, &tnum, sizeof(tnum));
> + SAFE_CLOSE(fd);
> +
> + fd = SAFE_OPEN(tc->referencefn2, O_RDONLY);
> + SAFE_READ(1, fd, &vnum, sizeof(vnum));
> + SAFE_CLOSE(fd);
> +
> + if (tnum == vnum) {
> + tst_res(TPASS,
> + "linkat is functionality correct");
> + } else {
> + tst_res(TFAIL,
> + "The link file's content isn't "
> + "as same as the original file's "
> + "although linkat returned 0");
Can we be shorter here and more to the point?
Something as:
tst_res(TFAIL, "Read wrong file content from the hard link.");
> }
Can we put this check that the file content is reacheable from the link
as well to a separat function?
> } else {
> - if (TEST_RETURN == 0)
> - tst_resm(TPASS,
> - "linkat succeeded as expected");
> - else
> - tst_resm(TPASS | TTERRNO,
> - "linkat failed as expected");
> + tst_res(TFAIL, "linkat failed");
If we are priting PASS/FAIL manually it would make more sense to use
TST_EXP_PASS() instead of the silent variant.
> }
> } else {
> - if (TEST_RETURN == 0)
> - tst_resm(TFAIL, "linkat succeeded unexpectedly");
> - else
> - tst_resm(TFAIL | TTERRNO,
> - "linkat failed unexpectedly; expected %d - %s",
> - desc->expected_errno,
> - strerror(desc->expected_errno));
> - }
> -}
> -
> -void setup(void)
> -{
> - char *cwd;
> - int fd;
> -
> - tst_sig(NOFORK, DEF_HANDLER, cleanup);
> -
> - tst_tmpdir();
> -
> - cwd = get_current_dir_name();
> - if (cwd == NULL) {
> - tst_brkm(TFAIL | TERRNO, cleanup,
> - "Failed to get current working directory");
> + TST_EXP_PASS(linkat(*tc->oldfd, tc->oldfn,
> + *tc->newfd, tc->newfn, tc->flags),
> + "linkat");
> }
> -
> - SAFE_MKDIR(cleanup, TEST_DIR1, 0700);
> - SAFE_MKDIR(cleanup, TEST_DIR3, 0700);
> - olddirfd = SAFE_OPEN(cleanup, TEST_DIR1, O_DIRECTORY);
> - deldirfd = SAFE_OPEN(cleanup, TEST_DIR3, O_DIRECTORY);
> - SAFE_RMDIR(cleanup, TEST_DIR3);
> - fd = SAFE_OPEN(cleanup, TEST_DIR1 "/" TEST_FILE1, O_CREAT | O_EXCL, 0600);
> - SAFE_CLOSE(cleanup, fd);
> - SAFE_MKFIFO(cleanup, TEST_DIR1 "/" TEST_FIFO, 0600);
> -
> - snprintf(dpathname, sizeof(dpathname), DPATHNAME_FMT, cwd);
> - snprintf(spathname, sizeof(spathname), SPATHNAME_FMT, cwd);
> -
> - free(cwd);
> }
>
> -static void cleanup(void)
> -{
> - tst_rmdir();
> -}
> +static struct tst_test test = {
> + .tcnt = ARRAY_SIZE(tcases),
> + .setup = setup,
> + .test = verify_linkat,
> + .needs_tmpdir = 1,
> +};
> diff --git a/testcases/kernel/syscalls/linkat/linkat03.c b/testcases/kernel/syscalls/linkat/linkat03.c
> new file mode 100644
> index 000000000..4ee25106e
> --- /dev/null
> +++ b/testcases/kernel/syscalls/linkat/linkat03.c
> @@ -0,0 +1,120 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) International Business Machines Corp., 2006
> + * Copyright (c) Linux Test Project, 2006-2024
> + */
> +
> +/*\
> + * [Description]
> + *
> + * Check the basic function of linkat that returns error.
> + */
> +
> +#define _GNU_SOURCE
> +
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <fcntl.h>
> +#include "tst_test.h"
> +#include "tst_safe_macros.h"
> +#include "lapi/syscalls.h"
> +#include "lapi/fcntl.h"
> +
> +#define TEST_DIR1 "olddir"
> +#define TEST_DIR2 "newdir"
> +#define TEST_DIR3 "deldir"
> +#define TEST_FILE1 "oldfile"
> +
> +static int olddirfd;
> +static int newdirfd = -1;
> +static int cwd_fd = AT_FDCWD;
> +static int stdinfd;
> +static int badfd = -1;
> +static int deldirfd;
> +
> +static struct tcase {
> + int *oldfd;
> + const char *oldfn;
> + int *newfd;
> + const char *newfn;
> + int flags;
> + const char *referencefn1;
> + const char *referencefn2;
These two pointers are not used for anything.
> + int expected_errno;
> +} tcases[] = {
> + /* 1. invalid directory to relative paths */
> + {&stdinfd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0,
> + 0, 0, ENOTDIR},
> + /* 2. relative paths to invalid directory */
> + {&olddirfd, TEST_FILE1, &stdinfd, TEST_DIR2 "/" TEST_FILE1, 0,
> + 0, 0, ENOTDIR},
> + /* 3. bad fd to relative paths */
> + {&badfd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0,
> + 0, 0, EBADF},
> + /* 4. relative paths to bad fd */
> + {&olddirfd, TEST_FILE1, &badfd, TEST_DIR2 "/" TEST_FILE1, 0,
> + 0, 0, EBADF},
> + /* 5. deleted to relative paths */
> + {&deldirfd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0,
> + 0, 0, ENOENT},
> + /* 6. relative paths to deleted */
> + {&olddirfd, TEST_FILE1, &deldirfd, TEST_DIR2 "/" TEST_FILE1, 0,
> + 0, 0, ENOENT},
> + /* 7. x-device link */
> + {&cwd_fd, "/proc/cpuinfo", &newdirfd, TEST_FILE1, 0, 0, 0, EXDEV},
> + /* 8. directory link */
> + {&olddirfd, ".", &newdirfd, TEST_FILE1, 0, 0, 0, EPERM},
> + /* 9. invalid flag */
> + {&olddirfd, TEST_FILE1, &newdirfd, TEST_FILE1, 1, 0, 0, EINVAL},
> +};
> +
> +static void setup(void)
> +{
> + char *cwd;
> + int fd;
> +
> + cwd = get_current_dir_name();
> + if (cwd == NULL) {
> + tst_brk(TFAIL | TERRNO,
> + "Failed to get current working directory.");
> + }
> +
> + SAFE_MKDIR(TEST_DIR1, 0700);
> + SAFE_MKDIR(TEST_DIR3, 0700);
> + olddirfd = SAFE_OPEN(TEST_DIR1, O_DIRECTORY);
> + deldirfd = SAFE_OPEN(TEST_DIR3, O_DIRECTORY);
> + SAFE_RMDIR(TEST_DIR3);
> + fd = SAFE_OPEN(TEST_DIR1 "/" TEST_FILE1, O_CREAT | O_EXCL, 0600);
> + SAFE_CLOSE(fd);
> +
> + free(cwd);
The cwd does not seem to be used at all.
> +}
> +
> +static void setup_every_case(void)
> +{
> + close(newdirfd);
> + rmdir(TEST_DIR2);
> +
> + SAFE_MKDIR(TEST_DIR2, 0700);
> + newdirfd = SAFE_OPEN(TEST_DIR2, O_DIRECTORY);
As far as I can tell this can be done once in the test setup()
> +}
> +
> +static void verify_linkat(unsigned int i)
> +{
> + struct tcase *tc = &tcases[i];
> +
> + setup_every_case();
> +
> + TST_EXP_FAIL(linkat(*tc->oldfd, tc->oldfn, *tc->newfd,
> + tc->newfn, tc->flags),
> + tc->expected_errno,
> + "linkat failed as expected");
> +}
> +
> +static struct tst_test test = {
> + .tcnt = ARRAY_SIZE(tcases),
> + .setup = setup,
> + .test = verify_linkat,
> + .needs_tmpdir = 1,
> +};
> --
> 2.39.3
>
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2024-07-17 11:40 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-25 6:01 [LTP] [PATCH] linkat01: Split into 2 cases and convert to new API Yang Xu via ltp
2024-07-17 11:43 ` Cyril Hrubis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox