forked from Minki/linux
a6d8a21596
Tests under alignment subdirectory are skipped when executed on previous generation hardware, but harness still marks them as failed. test: test_copy_unaligned tags: git_version:unknown [SKIP] Test skipped on line 26 skip: test_copy_unaligned selftests: copy_unaligned [FAIL] The MAGIC_SKIP_RETURN_VALUE value assigned to rc variable is retained till the program exit which causes the test to be marked as failed. This patch resets the value before returning to the main() routine. With this patch the test o/p is as follows: test: test_copy_unaligned tags: git_version:unknown [SKIP] Test skipped on line 26 skip: test_copy_unaligned selftests: copy_unaligned [PASS] Signed-off-by: Sachin Sant <sachinp@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
126 lines
2.2 KiB
C
126 lines
2.2 KiB
C
/*
|
|
* Copyright 2013, Michael Ellerman, IBM Corp.
|
|
* Licensed under GPLv2.
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
#include <elf.h>
|
|
#include <fcntl.h>
|
|
#include <link.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "subunit.h"
|
|
#include "utils.h"
|
|
|
|
#define KILL_TIMEOUT 5
|
|
|
|
static uint64_t timeout = 120;
|
|
|
|
int run_test(int (test_function)(void), char *name)
|
|
{
|
|
bool terminated;
|
|
int rc, status;
|
|
pid_t pid;
|
|
|
|
/* Make sure output is flushed before forking */
|
|
fflush(stdout);
|
|
|
|
pid = fork();
|
|
if (pid == 0) {
|
|
setpgid(0, 0);
|
|
exit(test_function());
|
|
} else if (pid == -1) {
|
|
perror("fork");
|
|
return 1;
|
|
}
|
|
|
|
setpgid(pid, pid);
|
|
|
|
/* Wake us up in timeout seconds */
|
|
alarm(timeout);
|
|
terminated = false;
|
|
|
|
wait:
|
|
rc = waitpid(pid, &status, 0);
|
|
if (rc == -1) {
|
|
if (errno != EINTR) {
|
|
printf("unknown error from waitpid\n");
|
|
return 1;
|
|
}
|
|
|
|
if (terminated) {
|
|
printf("!! force killing %s\n", name);
|
|
kill(-pid, SIGKILL);
|
|
return 1;
|
|
} else {
|
|
printf("!! killing %s\n", name);
|
|
kill(-pid, SIGTERM);
|
|
terminated = true;
|
|
alarm(KILL_TIMEOUT);
|
|
goto wait;
|
|
}
|
|
}
|
|
|
|
/* Kill anything else in the process group that is still running */
|
|
kill(-pid, SIGTERM);
|
|
|
|
if (WIFEXITED(status))
|
|
status = WEXITSTATUS(status);
|
|
else {
|
|
if (WIFSIGNALED(status))
|
|
printf("!! child died by signal %d\n", WTERMSIG(status));
|
|
else
|
|
printf("!! child died by unknown cause\n");
|
|
|
|
status = 1; /* Signal or other */
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static void alarm_handler(int signum)
|
|
{
|
|
/* Jut wake us up from waitpid */
|
|
}
|
|
|
|
static struct sigaction alarm_action = {
|
|
.sa_handler = alarm_handler,
|
|
};
|
|
|
|
void test_harness_set_timeout(uint64_t time)
|
|
{
|
|
timeout = time;
|
|
}
|
|
|
|
int test_harness(int (test_function)(void), char *name)
|
|
{
|
|
int rc;
|
|
|
|
test_start(name);
|
|
test_set_git_version(GIT_VERSION);
|
|
|
|
if (sigaction(SIGALRM, &alarm_action, NULL)) {
|
|
perror("sigaction");
|
|
test_error(name);
|
|
return 1;
|
|
}
|
|
|
|
rc = run_test(test_function, name);
|
|
|
|
if (rc == MAGIC_SKIP_RETURN_VALUE) {
|
|
test_skip(name);
|
|
/* so that skipped test is not marked as failed */
|
|
rc = 0;
|
|
} else
|
|
test_finish(name, rc);
|
|
|
|
return rc;
|
|
}
|