-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2016, 2017, Intel Corporation.
+ * Copyright (c) 2025, DataDirect Networks, Inc. All rights reserved.
*/
/*
* These tests exercise the llapi_layout API which abstracts the layout
* sudo ./llapi_layout_test
*/
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-#include <sys/signal.h>
-#include <sys/types.h>
#include <errno.h>
-#include <lustre/lustreapi.h>
-#include <pwd.h>
-#include <limits.h>
-#include <sys/stat.h>
+#include <fcntl.h>
#include <getopt.h>
#include <inttypes.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdint.h>
#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <lustre/lustreapi.h>
+#include "llapi_test_utils.h"
-#define ERROR(fmt, ...) \
- fprintf(stderr, "%s: %s:%d: %s: " fmt "\n", \
- program_invocation_short_name, __FILE__, __LINE__, \
- __func__, ## __VA_ARGS__);
-
-#define DIE(fmt, ...) \
-do { \
- ERROR(fmt, ## __VA_ARGS__); \
- exit(EXIT_FAILURE); \
-} while (0)
-
-#define ASSERTF(cond, fmt, ...) \
-do { \
- if (!(cond)) \
- DIE("assertion '%s' failed: "fmt, #cond, ## __VA_ARGS__);\
-} while (0) \
-
-static char *lustre_dir;
-static char *poolname;
-static bool run_list_provided;
-static int num_osts = -1;
-
-void usage(char *prog)
+static char *poolname = "testpool";
+static int num_osts = 2;
+static char lustre_dir[PATH_MAX - 5]; /* Lustre test directory */
+
+#define IN_RANGE(value, low, high) ((value >= low) && (value <= high))
+
+static void usage(char *prog)
{
printf("Usage: %s [-d lustre_dir] [-p pool_name] [-o num_osts] "
"[-s $n,$m,... (skip tests)] [-t $n,$m,... (run tests)]\n",
#define T0_STRIPE_SIZE 1048576
#define T0_OST_OFFSET (num_osts - 1)
#define T0_DESC "Read/write layout attributes then create a file"
-void test0(void)
+static void test0(void)
{
int rc;
int fd;
llapi_layout_free(layout);
}
-void __test1_helper(struct llapi_layout *layout)
+static void __test1_helper(struct llapi_layout *layout)
{
uint64_t ost0;
uint64_t ost1;
}
#define T1_DESC "Read test0 file by path and verify attributes"
-void test1(void)
+static void test1(void)
{
char path[PATH_MAX];
snprintf(path, sizeof(path), "%s/%s", lustre_dir, T0FILE);
struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
+
ASSERTF(layout != NULL, "errno = %d", errno);
__test1_helper(layout);
llapi_layout_free(layout);
}
#define T2_DESC "Read test0 file by FD and verify attributes"
-void test2(void)
+static void test2(void)
{
int fd;
int rc;
ASSERTF(fd >= 0, "open(%s): errno = %d", path, errno);
struct llapi_layout *layout = llapi_layout_get_by_fd(fd, 0);
+
ASSERTF(layout != NULL, "errno = %d", errno);
rc = close(fd);
}
#define T3_DESC "Read test0 file by FID and verify attributes"
-void test3(void)
+static void test3(void)
{
int rc;
struct llapi_layout *layout;
#define T4_STRIPE_COUNT 2
#define T4_STRIPE_SIZE 2097152
#define T4_DESC "Verify compatibility with 'lfs setstripe'"
-void test4(void)
+static void test4(void)
{
int rc;
uint64_t ost0;
errno = 0;
struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
+
ASSERTF(layout != NULL, "errno = %d", errno);
rc = llapi_layout_stripe_count_get(layout, &count);
#define T5FILE "t5"
#define T5_DESC "llapi_layout_get_by_path ENOENT handling"
-void test5(void)
+static void test5(void)
{
int rc;
char path[PATH_MAX];
}
#define T6_DESC "llapi_layout_get_by_fd EBADF handling"
-void test6(void)
+static void test6(void)
{
errno = 0;
struct llapi_layout *layout = llapi_layout_get_by_fd(9999, 0);
+
ASSERTF(layout == NULL && errno == EBADF, "errno = %d", errno);
}
#define T7FILE "t7"
#define T7_DESC "llapi_layout_get_by_path EACCES handling"
-void test7(void)
+static void test7(void)
{
int fd;
int rc;
ASSERTF(rc == 0, "errno = %d", errno);
errno = 0;
struct llapi_layout *layout = llapi_layout_get_by_path(path, 0);
+
ASSERTF(layout == NULL && errno == EACCES, "errno = %d", errno);
rc = seteuid(myuid);
ASSERTF(rc == 0, "errno = %d", errno);
}
/* llapi_layout_get_by_path() returns default layout for file with no
- * striping attributes. */
+ * striping attributes.
+ */
#define T8FILE "t8"
#define T8_DESC "llapi_layout_get_by_path ENODATA handling"
-void test8(void)
+static void test8(void)
{
int fd;
int rc;
/* Verify llapi_layout_patter_set() return values for various inputs. */
#define T9_DESC "verify llapi_layout_pattern_set() return values"
-void test9(void)
+static void test9(void)
{
struct llapi_layout *layout;
int rc;
/* Verify stripe_count interfaces return errors as expected */
#define T10_DESC "stripe_count error handling"
-void test10(void)
+static void test10(void)
{
int rc;
uint64_t count;
/* Verify stripe_size interfaces return errors as expected */
#define T11_DESC "stripe_size error handling"
-void test11(void)
+static void test11(void)
{
int rc;
uint64_t size;
/* Verify pool_name interfaces return errors as expected */
#define T12_DESC "pool_name error handling"
-void test12(void)
+static void test12(void)
{
int rc;
struct llapi_layout *layout;
#define T13FILE "t13"
#define T13_STRIPE_COUNT 2
#define T13_DESC "ost_index error handling"
-void test13(void)
+static void test13(void)
{
int rc;
int fd;
/* Verify llapi_layout_file_create() returns errors as expected */
#define T14_DESC "llapi_layout_file_create error handling"
-void test14(void)
+static void test14(void)
{
int rc;
struct llapi_layout *layout = llapi_layout_alloc();
#define T15FILE "t15"
#define T15_STRIPE_COUNT 2
#define T15_DESC "Can't change striping attributes of existing file"
-void test15(void)
+static void test15(void)
{
int rc;
int fd;
/* Default stripe attributes are applied as expected. */
#define T16FILE "t16"
#define T16_DESC "Default stripe attributes are applied as expected"
-void test16(void)
+static void test16(void)
{
int rc;
int fd;
rc = llapi_layout_stripe_count_get(filelayout, &fcount);
ASSERTF(rc == 0, "errno = %d", errno);
ASSERTF(fcount == dcount || dcount == LLAPI_LAYOUT_DEFAULT ||
- dcount == LLAPI_LAYOUT_WIDE,
+ IN_RANGE(dcount, LLAPI_LAYOUT_WIDE_MIN, LLAPI_LAYOUT_WIDE_MAX),
"%"PRIu64" != %"PRIu64, fcount, dcount);
rc = llapi_layout_stripe_size_get(filelayout, &fsize);
rc = llapi_layout_stripe_size_get(filelayout, &fsize);
ASSERTF(rc == 0, "errno = %d", errno);
ASSERTF(fcount == dcount || dcount == LLAPI_LAYOUT_DEFAULT ||
- dcount == LLAPI_LAYOUT_WIDE,
+ IN_RANGE(dcount, LLAPI_LAYOUT_WIDE_MIN, LLAPI_LAYOUT_WIDE_MAX),
"%"PRIu64" != %"PRIu64, fcount, dcount);
ASSERTF(fsize == dsize, "%"PRIu64" != %"PRIu64, fsize, dsize);
/* Setting stripe count to LLAPI_LAYOUT_WIDE uses all available OSTs. */
#define T17FILE "t17"
#define T17_DESC "LLAPI_LAYOUT_WIDE is honored"
-void test17(void)
+static void test17(void)
{
int rc;
int fd;
/* Setting pool with "fsname.pool" notation. */
#define T18FILE "t18"
#define T18_DESC "Setting pool with fsname.pool notation"
-void test18(void)
+static void test18(void)
{
int rc;
int fd;
}
#define T19_DESC "Maximum length pool name is NULL-terminated"
-void test19(void)
+static void test19(void)
{
struct llapi_layout *layout;
char *name = "0123456789abcde";
#define T20FILE "t20"
#define T20_DESC "LLAPI_LAYOUT_DEFAULT is honored"
-void test20(void)
+static void test20(void)
{
int rc;
int fd;
}
#define T21_DESC "llapi_layout_file_create fails for non-Lustre file"
-void test21(void)
+static void test21(void)
{
struct llapi_layout *layout;
char template[PATH_MAX];
ASSERTF(layout != NULL, "errno = %d", errno);
fd = llapi_layout_file_create(template, 0, 0640, layout);
- ASSERTF(fd == -1 && errno == ENOENT,
+ ASSERTF(fd == -1 && errno == ENOTTY,
"fd = %d, errno = %d, template = %s", fd, errno, template);
llapi_layout_free(layout);
}
#define T22FILE "t22"
#define T22_DESC "llapi_layout_file_create applied mode correctly"
-void test22(void)
+static void test22(void)
{
int rc;
int fd;
rc = unlink(path);
ASSERTF(rc == 0 || errno == ENOENT, "errno = %d", errno);
- umask_orig = umask(S_IWGRP | S_IWOTH);
+ umask_orig = umask(0022);
fd = llapi_layout_file_create(path, 0, mode_in, NULL);
ASSERTF(fd >= 0, "errno = %d", errno);
}
#define T23_DESC "llapi_layout_get_by_path fails for non-Lustre file"
-void test23(void)
+static void test23(void)
{
struct llapi_layout *layout;
char template[PATH_MAX];
}
/* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) returns expected layout
- * for file with unspecified layout. */
+ * for file with unspecified layout.
+ */
#define T24FILE "t24"
#define T24_DESC "LAYOUT_GET_EXPECTED works with existing file"
-void test24(void)
+static void test24(void)
{
int fd;
int rc;
}
/* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) returns expected layout
- * for directory with unspecified layout. */
+ * for directory with unspecified layout.
+ */
#define T25DIR "d25"
#define T25_DESC "LAYOUT_GET_EXPECTED works with directory"
-void test25(void)
+static void test25(void)
{
int rc;
struct llapi_layout *layout;
}
/* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) correctly combines
- * specified attributes of parent directory with attributes filesystem root. */
+ * specified attributes of parent directory with attributes filesystem root.
+ */
#define T26DIR "d26"
#define T26_DESC "LAYOUT_GET_EXPECTED partially specified parent"
#define T26_STRIPE_SIZE (1048576 * 4)
-void test26(void)
+static void test26(void)
{
int rc;
struct llapi_layout *layout;
}
/* llapi_layout_get_by_path(path, LAYOUT_GET_EXPECTED) work with
- * non existing file. */
+ * non existing file.
+ */
#define T27DIR "d27"
#define T27_DESC "LAYOUT_GET_EXPECTED with non existing file"
#define T27_STRIPE_SIZE (1048576 * 3)
-void test27(void)
+static void test27(void)
{
int rc;
struct llapi_layout *layout;
}
/* llapi_layout_stripe_count_get returns LLAPI_LAYOUT_WIDE for a directory
- * with a stripe_count of -1. */
+ * with a stripe_count of -1.
+ */
#define T28DIR "d28"
#define T28_DESC "LLAPI_LAYOUT_WIDE returned as expected"
-void test28(void)
+static void test28(void)
{
int rc;
struct llapi_layout *layout;
#define T29FILE "f29"
#define T29_DESC "set ost index to non-zero stripe number"
-void test29(void)
+static void test29(void)
{
int rc, fd, i;
uint64_t ost0, ost1, nost;
#define T30FILE "f30"
#define T30_DESC "create composite file, traverse components"
-void test30(void)
+static void test30(void)
{
int rc, fd;
uint64_t start[3], end[3];
ASSERTF(rc == 0, "errno %d", errno);
/* add component without adjusting previous component's extent
- * end will fail. */
+ * end will fail.
+ */
rc = llapi_layout_comp_add(layout);
ASSERTF(rc == -1 && errno == EINVAL, "rc %d, errno %d", rc, errno);
#define T31FILE "f31"
#define T31_DESC "add/delete component to/from existing file"
-void test31(void)
+static void test31(void)
{
int rc, fd, i;
uint64_t start[2], end[2];
#define T32FILE "t32"
#define T32_STRIPE_COUNT (num_osts*2)
#define T32_DESC "Test overstriping with layout_file_create"
-void test32(void)
+static void test32(void)
{
int rc;
int fd;
#define T33FILE "t33"
#define T33_STRIPE_COUNT (num_osts*2)
#define T33_DESC "Test overstriping with llapi_file_open"
-void test33(void)
+static void test33(void)
{
int rc;
int fd;
#define T34FILE "f34"
#define T34_DESC "create simple valid & invalid self extending layouts"
-void test34(void)
+static void test34(void)
{
int rc, fd;
uint64_t start[4], end[4];
ASSERTF(rc == 0, "errno %d", errno);
/* Set extension space flag on adjacent components:
- * This is invalid, but can't be checked until we try to create the
- * file. */
+ * This is invalid, but can't be checked until we create the file.
+ */
rc = llapi_layout_comp_flags_set(layout, LCME_FL_EXTENSION);
ASSERTF(rc == 0, "errno %d", errno);
rc = llapi_layout_comp_add(layout);
ASSERTF(rc == 0, "errno %d", errno);
- /* Convert this comp to zero-length so it can be followed by extension
- * space */
+ /* Convert this comp to 0-len that can be followed by extension space */
rc = llapi_layout_comp_extent_set(layout, start[2], start[2]);
ASSERTF(rc == 0, "errno %d", errno);
ASSERTF(rc == 0, "errno %d", errno);
}
-#define TEST_DESC_LEN 80
-struct test_tbl_entry {
- void (*tte_fn)(void);
- char tte_desc[TEST_DESC_LEN];
- bool tte_skip;
-};
-
static struct test_tbl_entry test_tbl[] = {
- { .tte_fn = &test0, .tte_desc = T0_DESC, .tte_skip = false },
- { .tte_fn = &test1, .tte_desc = T1_DESC, .tte_skip = false },
- { .tte_fn = &test2, .tte_desc = T2_DESC, .tte_skip = false },
- { .tte_fn = &test3, .tte_desc = T3_DESC, .tte_skip = false },
- { .tte_fn = &test4, .tte_desc = T4_DESC, .tte_skip = false },
- { .tte_fn = &test5, .tte_desc = T5_DESC, .tte_skip = false },
- { .tte_fn = &test6, .tte_desc = T6_DESC, .tte_skip = false },
- { .tte_fn = &test7, .tte_desc = T7_DESC, .tte_skip = false },
- { .tte_fn = &test8, .tte_desc = T8_DESC, .tte_skip = false },
- { .tte_fn = &test9, .tte_desc = T9_DESC, .tte_skip = false },
- { .tte_fn = &test10, .tte_desc = T10_DESC, .tte_skip = false },
- { .tte_fn = &test11, .tte_desc = T11_DESC, .tte_skip = false },
- { .tte_fn = &test12, .tte_desc = T12_DESC, .tte_skip = false },
- { .tte_fn = &test13, .tte_desc = T13_DESC, .tte_skip = false },
- { .tte_fn = &test14, .tte_desc = T14_DESC, .tte_skip = false },
- { .tte_fn = &test15, .tte_desc = T15_DESC, .tte_skip = false },
- { .tte_fn = &test16, .tte_desc = T16_DESC, .tte_skip = false },
- { .tte_fn = &test17, .tte_desc = T17_DESC, .tte_skip = false },
- { .tte_fn = &test18, .tte_desc = T18_DESC, .tte_skip = false },
- { .tte_fn = &test19, .tte_desc = T19_DESC, .tte_skip = false },
- { .tte_fn = &test20, .tte_desc = T20_DESC, .tte_skip = false },
- { .tte_fn = &test21, .tte_desc = T21_DESC, .tte_skip = false },
- { .tte_fn = &test22, .tte_desc = T22_DESC, .tte_skip = false },
- { .tte_fn = &test23, .tte_desc = T23_DESC, .tte_skip = false },
- { .tte_fn = &test24, .tte_desc = T24_DESC, .tte_skip = false },
- { .tte_fn = &test25, .tte_desc = T25_DESC, .tte_skip = false },
- { .tte_fn = &test26, .tte_desc = T26_DESC, .tte_skip = false },
- { .tte_fn = &test27, .tte_desc = T27_DESC, .tte_skip = false },
- { .tte_fn = &test28, .tte_desc = T28_DESC, .tte_skip = false },
- { .tte_fn = &test29, .tte_desc = T29_DESC, .tte_skip = false },
- { .tte_fn = &test30, .tte_desc = T30_DESC, .tte_skip = false },
- { .tte_fn = &test31, .tte_desc = T31_DESC, .tte_skip = false },
- { .tte_fn = &test32, .tte_desc = T32_DESC, .tte_skip = false },
- { .tte_fn = &test33, .tte_desc = T33_DESC, .tte_skip = false },
- { .tte_fn = &test34, .tte_desc = T34_DESC, .tte_skip = false },
+ TEST_REGISTER(0),
+ TEST_REGISTER(1),
+ TEST_REGISTER(2),
+ TEST_REGISTER(3),
+ TEST_REGISTER(4),
+ TEST_REGISTER(5),
+ TEST_REGISTER(6),
+ TEST_REGISTER(7),
+ TEST_REGISTER(8),
+ TEST_REGISTER(9),
+ TEST_REGISTER(10),
+ TEST_REGISTER(11),
+ TEST_REGISTER(12),
+ TEST_REGISTER(13),
+ TEST_REGISTER(14),
+ TEST_REGISTER(15),
+ TEST_REGISTER(16),
+ TEST_REGISTER(17),
+ TEST_REGISTER(18),
+ TEST_REGISTER(19),
+ TEST_REGISTER(20),
+ TEST_REGISTER(21),
+ TEST_REGISTER(22),
+ TEST_REGISTER(23),
+ TEST_REGISTER(24),
+ TEST_REGISTER(25),
+ TEST_REGISTER(26),
+ TEST_REGISTER(27),
+ TEST_REGISTER(28),
+ TEST_REGISTER(29),
+ TEST_REGISTER(30),
+ TEST_REGISTER(31),
+ TEST_REGISTER(32),
+ TEST_REGISTER(33),
+ TEST_REGISTER(34),
+ TEST_REGISTER_END
};
-#define NUM_TESTS (sizeof(test_tbl) / sizeof(struct test_tbl_entry))
-
-void print_test_desc(int test_num, const char *test_desc, const char *status)
-{
- int i;
-
- printf(" test %2d: %s ", test_num, test_desc);
- for (i = 0; i < TEST_DESC_LEN - strlen(test_desc); i++)
- printf(".");
- printf(" %s\n", status);
-}
-
-/* This function runs a single test by forking the process. This way,
- * if there is a segfault during a test, the test program won't crash. */
-int test(void (*test_fn)(), const char *test_desc, bool test_skip, int test_num)
-{
- int rc = 0;
- pid_t pid;
- char status_buf[128];
-
- if (test_skip) {
- if (!run_list_provided)
- print_test_desc(test_num, test_desc, "skip");
- return 0;
- }
-
- pid = fork();
- if (pid < 0) {
- ERROR("cannot fork: %s", strerror(errno));
- } else if (pid > 0) {
- int status = 0;
-
- /* Non-zero value indicates failure. */
- wait(&status);
- if (status == 0) {
- strncpy(status_buf, "pass", sizeof(status_buf));
- } else if WIFSIGNALED(status) {
- snprintf(status_buf, sizeof(status_buf),
- "fail (exit status %d, killed by SIG%d)",
- WEXITSTATUS(status), WTERMSIG(status));
- rc = -1;
- } else {
- snprintf(status_buf, sizeof(status_buf),
- "fail (exit status %d)", WEXITSTATUS(status));
- rc = -1;
- }
- print_test_desc(test_num, test_desc, status_buf);
- } else if (pid == 0) {
- /* Run the test in the child process. Exit with 0 for success,
- * non-zero for failure */
- test_fn();
- exit(0);
- }
-
- return rc;
-}
-
-/* 'str_tests' are the tests to be skipped, such as "1,3,4,.." */
-static void set_tests_skipped(char *str_tests)
-{
- char *ptr = str_tests;
- int tstno;
-
- if (ptr == NULL || strlen(ptr) == 0)
- return;
-
- while (*ptr != '\0') {
- tstno = strtoul(ptr, &ptr, 0);
- if (tstno >= 0 && tstno < NUM_TESTS)
- test_tbl[tstno].tte_skip = true;
- if (*ptr == ',')
- ptr++;
- else
- break;
- }
-}
-
-static void set_tests_to_run(char *str_tests)
-{
- char *ptr = str_tests;
- int tstno;
- int i = 0;
-
- if (ptr == NULL || strlen(ptr) == 0)
- return;
-
- for (i = 0; i < NUM_TESTS ; i++)
- test_tbl[i].tte_skip = true;
-
- while (*ptr != '\0') {
- tstno = strtoul(ptr, &ptr, 0);
- if (tstno >= 0 && tstno < NUM_TESTS)
- test_tbl[tstno].tte_skip = false;
- if (*ptr == ',')
- ptr++;
- else
- break;
- }
-}
-
static void process_args(int argc, char *argv[])
{
int c;
while ((c = getopt(argc, argv, "d:p:o:s:t:")) != -1) {
switch (c) {
case 'd':
- lustre_dir = optarg;
+ if (snprintf(lustre_dir, sizeof(lustre_dir), "%s",
+ optarg) >= sizeof(lustre_dir))
+ DIE("Error: test directory name too long\n");
break;
case 'p':
poolname = optarg;
break;
case 'o':
num_osts = atoi(optarg);
+ if (num_osts < 2)
+ DIE("Error: at least 2 OSTS are required\n");
break;
case 's':
- set_tests_skipped(optarg);
+ set_tests_to_skip(optarg, test_tbl);
break;
case 't':
- run_list_provided = true;
- set_tests_to_run(optarg);
+ set_tests_to_run(optarg, test_tbl);
break;
case '?':
fprintf(stderr, "Unknown option '%c'\n", optopt);
int main(int argc, char *argv[])
{
- int rc = 0;
- int i;
- struct stat s;
- char fsname[8 + 1];
-
- llapi_msg_set_level(LLAPI_MSG_OFF);
-
process_args(argc, argv);
- if (lustre_dir == NULL)
- lustre_dir = "/mnt/lustre";
- if (poolname == NULL)
- poolname = "testpool";
- if (num_osts == -1)
- num_osts = 2;
-
- if (num_osts < 2)
- DIE("Error: at least 2 OSTS are required\n");
-
- if (stat(lustre_dir, &s) < 0)
- DIE("cannot stat %s: %s\n", lustre_dir, strerror(errno));
- else if (!S_ISDIR(s.st_mode))
- DIE("%s: not a directory\n", lustre_dir);
-
- rc = llapi_search_fsname(lustre_dir, fsname);
- if (rc != 0) {
- fprintf(stderr, "Error: %s: not a Lustre filesystem\n",
- lustre_dir);
- exit(EXIT_FAILURE);
- }
-
- /* Play nice with Lustre test scripts. Non-line buffered output
- * stream under I/O redirection may appear incorrectly. */
- setvbuf(stdout, NULL, _IOLBF, 0);
-
- for (i = 0; i < NUM_TESTS; i++) {
- struct test_tbl_entry *tst = &test_tbl[i];
- if (test(tst->tte_fn, tst->tte_desc, tst->tte_skip, i) != 0)
- rc++;
- }
- return rc;
+ return run_tests(lustre_dir, test_tbl);
}