| /* |
| * |
| * Copyright (c) International Business Machines Corp., 2001 |
| * |
| * 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: epoll-ltp.c |
| |
| Description: |
| Test the epoll_* system calls. This test program attempts to |
| be very thorough in exercising epoll_* system calls. Large |
| combinations of valid and invalid parameters are passed with |
| valid and invalid sequences. Due to the combinatorial nature |
| of this test program the test may take a "long" time to |
| execute. |
| |
| Total Tests: 2 (2 system calls are being tested for) |
| |
| Test Name: epoll_create, epoll_ctl |
| |
| Test Assertion |
| & Strategy: Test a variety of incorrect parameters for epoll_create |
| |
| Then run a reasonable epoll_create and get a fd for the epoll |
| set. |
| |
| Next run epoll_ctl on that fd (epoll_fd) with a variety of |
| incorrect parameters and a couple correct ones. |
| |
| Finally ?How to thoroughly test epoll_wait? |
| |
| Author: Matt Helsley <matthltc@us.ibm.com> |
| |
| History: Created - May 22 2003 - Matt Helsley <matthltc@us.ibm.com> |
| Added - |
| |
| Notes: Currently we assume that the OS will never allocate an fd s.t. |
| fd == INT_MAX and that it will instead choose to allocate fds |
| from the "low" numbers. -MH |
| |
| Currently pokes epoll_create several times in 2 + NUM_RAND_ATTEMPTS ways |
| pokes epoll_ctl 27648 - (2 + NUM_RAND_ATTEMPTS) ways |
| does not poke epoll_wait |
| |
| TODO: change errno test code to build lists of possible errno values for |
| each erroneous parameter. Check that the errno value is in one |
| of the lists. Currently errno is not checked at all when multiple |
| erroneous parameters are passed in. |
| |
| test epoll_ctl with a large number of file descriptor events in the |
| set |
| |
| Link against epoll and ltp (-lepoll -lltp) |
| |
| *******************************************************************************/ |
| |
| #ifndef _GNU_SOURCE |
| #define _GNU_SOURCE |
| #endif |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <stdarg.h> |
| #include <string.h> |
| #include <signal.h> |
| #include <assert.h> |
| #include <limits.h> |
| #include <ctype.h> |
| #include <time.h> |
| #include <errno.h> |
| #include <signal.h> |
| #include <sys/types.h> |
| #include <sys/time.h> |
| #include <sys/file.h> |
| #include <sys/ioctl.h> |
| #include <sys/mman.h> |
| #include <sys/select.h> |
| #include <sys/wait.h> |
| |
| #include "config.h" |
| #include "test.h" |
| |
| char *TCID = "epoll01"; |
| int TST_TOTAL = 1; |
| |
| #ifdef HAVE_SYS_EPOLL_H |
| |
| #include <sys/epoll.h> |
| |
| /* Local Defines */ |
| #if !defined(TRUE) && !defined(FALSE) |
| #define TRUE 1 |
| #define FALSE 0 |
| #endif |
| |
| #define NUM_RAND_ATTEMPTS 16 |
| #define BACKING_STORE_SIZE_HINT 32 |
| |
| /* |
| Define the beginning of a "protected region". |
| This is a region where a wide variety of errors |
| could occur or signals could arrive (including |
| SIGSEGV and SIGKILL). |
| $ |
| The test program uses this to catch those |
| conditions as best it can and continue testing. |
| |
| The region MUST be marked by a corresponding |
| PROTECT_REGION_END. |
| |
| DO NOT nest protected regions! i.e. Do not build |
| code of the form: |
| |
| PROTECT_REGION_START |
| ... |
| PROTECT_REGION_START |
| ... |
| PROTECT_REGION_END |
| ... |
| PROTECT_REGION_END |
| */ |
| #define PROTECT_REGION_START \ |
| do { \ |
| pid_t kid_pid; \ |
| int kid_status; \ |
| \ |
| tst_old_flush(); \ |
| kid_pid = FORK_OR_VFORK(); \ |
| if (kid_pid == 0) { |
| |
| #define PROTECT_REGION_EXIT(errval) return (errval); |
| |
| #define PROTECT_REGION_END(result, errval) \ |
| return 0; \ |
| } else { \ |
| waitpid(kid_pid, &kid_status, 0); \ |
| if (WIFEXITED(kid_status)) { \ |
| (result) = WEXITSTATUS(kid_status); \ |
| } else { /* Must have been signaled */ \ |
| (result) = (errval); \ |
| if (WIFSIGNALED(kid_status)) \ |
| tst_resm(TFAIL, "Protected function test exited due to signal %d (%s)", \ |
| WTERMSIG(kid_status), strsignal(WTERMSIG(kid_status))); \ |
| } \ |
| } \ |
| } while (0) |
| |
| /* |
| * Call a function in a "protected" context. |
| * This protects the test program proper from segfaults |
| * and allows for the extraction of an integer return |
| * code. |
| * |
| * return only integer results. |
| */ |
| #define PROTECT_FUNC(fn, errval, epoll_fd) ( \ |
| { \ |
| pid_t kid_pid; \ |
| int kid_status; \ |
| \ |
| tst_old_flush(); \ |
| kid_pid = FORK_OR_VFORK(); \ |
| if (kid_pid == 0) { /* Run the function */ \ |
| return fn(epoll_fd); \ |
| } else { \ |
| waitpid(kid_pid, &kid_status, 0); \ |
| if (WIFEXITED(kid_status)) { \ |
| kid_status = WEXITSTATUS(kid_status); \ |
| } else { /* Must have been signaled */ \ |
| kid_status = (errval); \ |
| if (WIFSIGNALED(kid_status)) \ |
| tst_resm(TFAIL, "Protected function test exited due to signal %d (%s)", \ |
| WTERMSIG(kid_status), strsignal(WTERMSIG(kid_status))); \ |
| } \ |
| } \ |
| kid_status = kid_status;}) |
| |
| /* |
| * Given the number of random size requests to test, |
| * test various boundary cases of epoll_create(). |
| * |
| * Return the number of tests that failed. 0 indicates |
| * 100% passed. |
| */ |
| int test_epoll_create(unsigned int num_rand_attempts) |
| { |
| int epoll_fd = -1; |
| int fd_set_size = -1; |
| unsigned int attempt_count; |
| unsigned int num_epoll_create_test_fails = 0; |
| unsigned int num_epoll_create_test_calls = 0; |
| |
| /* Negative set sizes */ |
| errno = 0; |
| fd_set_size = -1; |
| num_epoll_create_test_calls++; |
| epoll_fd = epoll_create(fd_set_size); |
| if (epoll_fd >= 0) { |
| tst_resm(TFAIL | TERRNO, |
| "epoll_create with negative set size succeeded unexpectedly"); |
| num_epoll_create_test_fails++; |
| close(epoll_fd); |
| } else { |
| if (errno != EINVAL) { |
| tst_resm(TFAIL | TERRNO, |
| "epoll_create with negative set size didn't set errno to EINVAL"); |
| num_epoll_create_test_fails++; |
| } else { |
| tst_resm(TPASS, "epoll_create with negative set size"); |
| } |
| } |
| |
| /* Large set sizes -- try several less than or equal to INT_MAX by some |
| small amount (expect num_rand_attempts to be approximately the |
| amount we'd like to go below INT_MAX). */ |
| fd_set_size = INT_MAX; |
| for (attempt_count = num_rand_attempts; attempt_count > 0; |
| attempt_count--, fd_set_size--) { |
| num_epoll_create_test_calls++; |
| epoll_fd = epoll_create(fd_set_size); |
| if (epoll_fd == -1) { |
| if (errno != ENOMEM) { |
| tst_resm(TFAIL, |
| "epoll_create with large set size (size = %d)", |
| fd_set_size); |
| num_epoll_create_test_fails++; |
| } else { |
| tst_resm(TPASS, |
| "epoll_create with large set size (size = %d)", |
| fd_set_size); |
| } |
| } else { |
| tst_resm(TPASS, |
| "epoll_create with large set size (size = %d)", |
| fd_set_size); |
| close(epoll_fd); |
| } |
| } |
| |
| /* Random large set sizes */ |
| for (attempt_count = num_rand_attempts; attempt_count > 0; |
| attempt_count--) { |
| fd_set_size = abs(rand() + SHRT_MAX) % INT_MAX; |
| errno = 0; |
| num_epoll_create_test_calls++; |
| epoll_fd = epoll_create(fd_set_size); |
| if (epoll_fd < 0) { |
| if (errno != ENOMEM) { |
| tst_resm(TFAIL, |
| "epoll_create with random random large set size (size = %d)", |
| fd_set_size); |
| num_epoll_create_test_fails++; |
| } else { |
| tst_resm(TPASS, |
| "epoll_create with random random large set size (size = %d)", |
| fd_set_size); |
| } |
| } else { |
| tst_resm(TPASS, |
| "epoll_create with random large set size (size = %d)", |
| fd_set_size); |
| close(epoll_fd); |
| } |
| } |
| |
| tst_resm(TINFO, |
| "Summary: Of %d tests, epoll_create failed %d (%3.0f%% passed).", |
| num_epoll_create_test_calls, num_epoll_create_test_fails, |
| ((float) |
| (num_epoll_create_test_calls - num_epoll_create_test_fails) |
| * 100.0f / (float) |
| num_epoll_create_test_calls)); |
| /* Return 0 on success. */ |
| |
| return num_epoll_create_test_fails; |
| } |
| |
| /* RES_PASS indicates a PASS result */ |
| #define RES_PASS 0 |
| |
| /* |
| * RES_FAIL_* indicates a FAIL result |
| * In brief, there are two things that can go wrong in a |
| * failiure. The return value (result = epoll_ctl(...)) and |
| * the errno value may not match expectations. In this notation, |
| * MIS -> mismatch, MAT -> match, BAD -> bad, and IGN -> ignored. |
| * |
| * RETV_MIS_* indicates the return value was either 0 or 1, but did |
| * not match the expected return value |
| * |
| * _RETV_MAT_* indicates that the return value was 0 xor 1 and did |
| * match the expected value |
| * |
| *_RETV_BAD_* the return value was neither 0 nor 1. |
| *_ERRNO_MAT the error number matched the expected number |
| *_ERRNO_MIS the error number did not match the expected number |
| *_ERRNO_IGN no error number was expected and so errno was ignored |
| * |
| * Keep these values below 256 as only 1 byte gets passed as a |
| * return value for the process. Note that RES_PASS is 0 which |
| * LTP interprets as a PASS. |
| */ |
| |
| /* Did not get the expected return value, but errno value was expected */ |
| #define RES_FAIL_RETV_MIS_ERRNO_MAT 1 |
| /* Did not get the expected return value, but errno value was expected */ |
| #define RES_FAIL_RETV_BAD_ERRNO_MAT 2 |
| /* Did get the expected return value, and errno value was not expected */ |
| #define RES_FAIL_RETV_MAT_ERRNO_MIS 3 |
| /* Return value was neither 0 nor -1. Mismatch in value of errno */ |
| #define RES_FAIL_RETV_BAD_ERRNO_MIS 4 |
| /* Did not get the expected return value and errno is irrelevant */ |
| #define RES_FAIL_RETV_MIS_ERRNO_IGN 5 |
| /* Return value was neither 0 nor -1. value of errno is irrelevant */ |
| #define RES_FAIL_RETV_BAD_ERRNO_IGN 6 |
| /* We expected multiple errors so we were unable to check errno for conformance */ |
| #define RES_PASS_RETV_MAT_ERRNO_IGN 7 |
| |
| static const char *result_strings[] = { |
| "Passed", |
| "Return value mismatched yet errno matched.", |
| "Return value was bad yet errno matched.", |
| "Return value matched yet errno mismatched.", |
| "Return value was bad and errno mismatched.", |
| "Return value mismatched so errno ignored.", |
| "Return value was bad so errno ignored.", |
| "Return value matched but errno ignored. (multiple errors expected)" |
| }; |
| |
| /****************************************************************************************/ |
| /* This macro helps keep the code below understandable. It prints out the |
| failiure message passed to it plus the parameters to the system call. */ |
| #define EPOLL_CTL_TEST_RESULTS_SHOW_PARAMS 1 |
| #if EPOLL_CTL_TEST_RESULTS_SHOW_PARAMS |
| #define EPOLL_CTL_TEST_FAIL(msg , ...) \ |
| ({ \ |
| if (ev_ptr != NULL) { \ |
| tst_resm(TFAIL, ( "(epoll_ctl(%d,%08x,%d,%p = {%08x,%08d}) returned %d:%s)" ) , ##__VA_ARGS__ , \ |
| epoll_fds[epfd_index], epoll_ctl_ops[op_index], \ |
| epoll_fds[fd_index], ev_ptr, ev_ptr->events, ev_ptr->data.fd, errno, \ |
| strerror(errno)); \ |
| } else { \ |
| tst_resm(TFAIL, ( "(epoll_ctl(%d,%08x,%d,%p) returned %d:%s)" ) , ##__VA_ARGS__ , \ |
| epoll_fds[epfd_index], epoll_ctl_ops[op_index], \ |
| epoll_fds[fd_index], ev_ptr, errno, strerror(errno)); \ |
| } \ |
| }) |
| |
| #define EPOLL_CTL_TEST_PASS(msg , ...) \ |
| ({ \ |
| if (ev_ptr != NULL) { \ |
| tst_resm(TPASS, ( "(epoll_ctl(%d,%08x,%d,%p = {%08x,%08d}) returned %d:%s)" ) , ##__VA_ARGS__ , \ |
| epoll_fds[epfd_index], epoll_ctl_ops[op_index], \ |
| epoll_fds[fd_index], ev_ptr, ev_ptr->events, ev_ptr->data.fd, errno, \ |
| strerror(errno)); \ |
| } else { \ |
| tst_resm(TPASS, ( "(epoll_ctl(%d,%08x,%d,%p) returned %d:%s)" ) , ##__VA_ARGS__ , \ |
| epoll_fds[epfd_index], epoll_ctl_ops[op_index], \ |
| epoll_fds[fd_index], ev_ptr, errno, strerror(errno)); \ |
| } \ |
| }) |
| #else |
| #define EPOLL_CTL_TEST_FAIL(msg , ...) tst_resm(TFAIL, msg , ##__VA_ARGS__) |
| #define EPOLL_CTL_TEST_PASS(msg , ...) tst_resm(TPASS, msg , ##__VA_ARGS__) |
| #endif |
| |
| /****************************************************************************************/ |
| |
| int test_epoll_ctl(int epoll_fd) |
| { |
| int fds[] = { -1, INT_MAX }; |
| int epoll_fds[] = { 0, -1, 0, INT_MAX }; |
| int epoll_events[64]; |
| /* The list of operations to try AND THE ORDER THEY ARE TRIED IN */ |
| int epoll_ctl_ops[] = |
| { EPOLL_CTL_DEL, EPOLL_CTL_MOD, EPOLL_CTL_ADD, EPOLL_CTL_MOD, |
| EPOLL_CTL_DEL, EPOLL_CTL_MOD, EPOLL_CTL_DEL, INT_MAX, -1 |
| }; |
| struct epoll_event event; |
| char event_mem[sizeof(struct epoll_event) * 2]; |
| struct epoll_event *unaligned_event_ptr; |
| |
| /* Indices into lists */ |
| int index = 0; /* multi-use index. First uses are to initialize |
| lists. Second use is to iterate over the implicit |
| list of structs to pass in */ |
| unsigned int epfd_index; /* index into fd list for the epfd parameter */ |
| unsigned int event_index; /* index into event list for the events field of the |
| struct epoll_event parameter */ |
| unsigned int fd_index; /* index into fd list for the fd parameter */ |
| unsigned int op_index; /* index into the list of operations for the op |
| parameter */ |
| unsigned int num_epoll_ctl_test_fails = 0; |
| unsigned int num_epoll_ctl_test_calls = 0; |
| |
| /* Generate all possible combinations of events (2^6 == 64) |
| Assume we know nothing about the EPOLL event types _except_ |
| that they describe bits in a set. */ |
| for (index = 0; index < 64; index++) { |
| epoll_events[index] = ((EPOLLIN * ((index & 0x01) >> 0)) | |
| (EPOLLOUT * ((index & 0x02) >> 1)) | |
| (EPOLLPRI * ((index & 0x04) >> 2)) | |
| (EPOLLERR * ((index & 0x08) >> 3)) | |
| (EPOLLHUP * ((index & 0x10) >> 4)) | |
| (EPOLLET * ((index & 0x20) >> 5))); |
| } |
| |
| /* Get a pointer to an unaligned struct epoll_event */ |
| { |
| char *unalign_ptr = event_mem; |
| |
| unalign_ptr = |
| unalign_ptr + (((unsigned long)unalign_ptr & 1) ? 0 : 1); |
| unaligned_event_ptr = (struct epoll_event *)unalign_ptr; |
| } |
| |
| /* One of the fds we want to test is the valid one */ |
| epoll_fds[0] = epoll_fd; |
| |
| /* Test out all of the interesting combinations. This is going to |
| take a while (in compute cycles). It took less than 1 minute to |
| run on a PIII 500 without checking the results. */ |
| for (index = 0; index < 3; index++) { |
| struct epoll_event *ev_ptr = NULL; |
| |
| switch (index) { |
| case 0: /* Pass aligned struct */ |
| event.data.u64 = 0; |
| ev_ptr = &event; |
| break; |
| case 1: /* Pass unaligned struct */ |
| unaligned_event_ptr->data.u64 = 0; |
| ev_ptr = unaligned_event_ptr; |
| break; |
| case 2: |
| default: /* Pass NULL ptr */ |
| ev_ptr = NULL; |
| break; |
| } |
| |
| for (epfd_index = 0; |
| epfd_index < (sizeof(epoll_fds) / sizeof(int)); |
| epfd_index++) { |
| for (event_index = 0; |
| event_index < (sizeof(epoll_events) / sizeof(int)); |
| event_index++) { |
| for (fd_index = 0; |
| fd_index < (sizeof(fds) / sizeof(int)); |
| fd_index++) { |
| /* Now epoll_fd is a descriptor that references the set of |
| file descriptors we are interested in. Next we test epoll_ctl */ |
| for (op_index = 0; |
| op_index < |
| (sizeof(epoll_ctl_ops) / |
| sizeof(int)); op_index++) { |
| int result; |
| int expected_errno = 0; |
| int num_errors_expected = 0; |
| |
| if (ev_ptr != NULL) |
| ev_ptr->events = |
| epoll_events |
| [event_index]; |
| |
| /* Perform the call itself. Put it in a protected region which |
| returns -1 in the variable result if a protection violation |
| occurs (see PROTECT_REGION_END for the result) */ |
| PROTECT_REGION_START errno = 0; |
| |
| /* NOTE that we are assuming that epoll will operate across |
| a fork() call such that a subsequent fork() in the parent |
| will also manipulate the same set */ |
| result = |
| epoll_ctl(epoll_fds |
| [epfd_index], |
| epoll_ctl_ops |
| [op_index], |
| fds[fd_index], |
| ev_ptr); |
| |
| /* We can't test errno resulting from the epoll_ctl call outside of |
| the PROTECT_REGION hence we do not have a PROTECT_REGION_END |
| here */ |
| |
| /* |
| Test the results. Look for appropriate error conditions |
| */ |
| |
| /* Check the epfd */ |
| if (epoll_fds[epfd_index] != |
| epoll_fd) { |
| /* Expect an error */ |
| if (epoll_fds |
| [epfd_index] == 0) |
| expected_errno = |
| EINVAL; |
| else /* epfd is not a valid file descriptor since it is |
| neither epoll_fd nor stdin */ |
| expected_errno = |
| EBADF; |
| num_errors_expected++; |
| } |
| |
| switch (epoll_ctl_ops[op_index]) { |
| case EPOLL_CTL_ADD: |
| case EPOLL_CTL_MOD: |
| case EPOLL_CTL_DEL: |
| break; |
| default: /* Expect an error */ |
| expected_errno = EINVAL; |
| num_errors_expected++; |
| break; |
| } |
| |
| expected_errno = EPERM; |
| num_errors_expected++; |
| |
| if (ev_ptr == NULL) { |
| expected_errno = EINVAL; |
| num_errors_expected++; |
| } else if ((ev_ptr == &event) |
| || (ev_ptr == |
| unaligned_event_ptr)) |
| { |
| if (ev_ptr->events == 0) { |
| expected_errno = |
| EINVAL; |
| num_errors_expected++; |
| } |
| |
| for (index = 1; |
| index < 64; |
| index++) { |
| if (ev_ptr->events != epoll_events[index]) { |
| expected_errno |
| = |
| EINVAL; |
| num_errors_expected++; |
| } |
| } |
| } else { |
| /* Do not expect an error */ |
| } |
| |
| if (num_errors_expected == 0) { |
| /* We did not expect an error */ |
| if (result == 0) { |
| /* We didn't get an error. Think of this as RES_PASS_RETV_MAT_ERRNO_IGN */ |
| return RES_PASS; |
| } else if (result == -1) { /* The return value is -1, so it's not bad */ |
| return |
| RES_FAIL_RETV_MIS_ERRNO_IGN; |
| } else { |
| return |
| RES_FAIL_RETV_BAD_ERRNO_IGN; |
| } |
| } else if (num_errors_expected |
| == 1) { |
| /* We expected an error */ |
| if (result == 0) { |
| return RES_FAIL_RETV_MIS_ERRNO_IGN; /* Unexpected success */ |
| } else if (result == -1) { |
| /* We got an error. Check errno */ |
| if (errno == |
| expected_errno) |
| { |
| return RES_PASS; /* think of this as RETV_MAT_ERRNO_MAT */ |
| } else { |
| return |
| RES_FAIL_RETV_MAT_ERRNO_MIS; |
| } |
| } else { |
| /* We got a bad return code! Interpret this as |
| getting an error and check errno. */ |
| if (errno == |
| expected_errno) |
| return |
| RES_FAIL_RETV_BAD_ERRNO_MAT; |
| else |
| return |
| RES_FAIL_RETV_BAD_ERRNO_MIS; |
| } |
| } else if (num_errors_expected > |
| 1) { |
| /* We expected multiple errors */ |
| if (result == 0) { |
| return RES_FAIL_RETV_MIS_ERRNO_IGN; /* Unexpected success */ |
| } else if (result == -1) { |
| /* We got an error. Check errno */ |
| if (errno == |
| expected_errno) |
| { |
| return RES_PASS; /* think of this as RETV_MAT_ERRNO_MAT */ |
| } else { |
| /* Ignore errno because the desired value is unknowable |
| without looking at the structure of the code. */ |
| return |
| RES_PASS_RETV_MAT_ERRNO_IGN; |
| } |
| } else { |
| /* We got a bad return code! Interpret this as |
| getting an error and check errno. */ |
| if (errno == |
| expected_errno) |
| /* Don't Ignore errno because the desired value |
| happened to match what we expected. */ |
| return |
| RES_FAIL_RETV_BAD_ERRNO_MAT; |
| else |
| /* Ignore errno because the desired value is unknowable |
| without looking at the structure of the code. */ |
| return |
| RES_FAIL_RETV_BAD_ERRNO_IGN; |
| } |
| } |
| |
| /* All "return"s between PROTECT_REGION_BEGIN |
| and PROTECT_REGION_END place their value in |
| the result parameter. If the region caused |
| a protection violation (segfault or otherwise) |
| then the result is set to the second parameter's |
| value (-1 in this case). */ |
| PROTECT_REGION_END(result, -1); |
| |
| /* Count the number of tests run */ |
| num_epoll_ctl_test_calls++; |
| |
| /* Now test the result */ |
| if (!((result == RES_PASS) |
| || (result == |
| RES_PASS_RETV_MAT_ERRNO_IGN))) |
| { |
| if (result > |
| (sizeof |
| (result_strings) / |
| sizeof(const char |
| *))) { |
| /* Returned a result which has no corresponding text description */ |
| EPOLL_CTL_TEST_FAIL |
| ("FIXME FIX ME BUG in Test Program itself!"); |
| } else { |
| if (result == -1) /* Segfault during epoll_ctl call */ |
| EPOLL_CTL_TEST_FAIL |
| ("Test arguments caused abnormal exit."); |
| else /* The 'normal' failiure */ |
| EPOLL_CTL_TEST_FAIL |
| ((result_strings[result])); |
| } |
| num_epoll_ctl_test_fails++; |
| #ifdef DEBUG |
| } else /* The call of epoll_ctl behaved as expected */ |
| EPOLL_CTL_TEST_PASS((result_strings[result])); |
| #else |
| } |
| #endif |
| } |
| } |
| } |
| } |
| close(epoll_fd); |
| } |
| |
| tst_resm(TINFO, |
| "Summary: Of %d tests, epoll_ctl failed %d (%3.0f%% passed).", |
| num_epoll_ctl_test_calls, num_epoll_ctl_test_fails, |
| ((float)(num_epoll_ctl_test_calls - num_epoll_ctl_test_fails) * |
| 100.0f / (float)num_epoll_ctl_test_calls)); |
| return (num_epoll_ctl_test_fails / num_epoll_ctl_test_calls); |
| } |
| |
| int main(int argc, char **argv) |
| { |
| int epoll_fd; |
| struct timeval tv; |
| int last_result; |
| |
| tst_resm(TINFO, "testing if epoll() system call works"); |
| |
| /* Get the current time */ |
| if (gettimeofday(&tv, NULL) != 0) { |
| tst_brkm(TBROK | TERRNO, NULL, "gettimeofday failed"); |
| } else { |
| tst_resm(TINFO, "gettimeofday() works"); |
| } |
| |
| /* Set up RNG */ |
| srand(tv.tv_usec); |
| tst_resm(TINFO, |
| "random number seeded with gettimeofday() [seed = %ld] works", |
| tv.tv_usec); |
| |
| tst_resm(TINFO, "Testing epoll_create"); |
| /* Testing epoll_create with some different sizes */ |
| last_result = PROTECT_FUNC(test_epoll_create, -1, NUM_RAND_ATTEMPTS); |
| if (last_result != 0) { |
| /* create test(s) failed */ |
| } |
| |
| /* Create an epoll_fd for testing epoll_ctl */ |
| epoll_fd = epoll_create(BACKING_STORE_SIZE_HINT); |
| if (epoll_fd < 0) { |
| tst_brkm(TFAIL | TERRNO, NULL, "epoll_create failed"); |
| } |
| |
| tst_resm(TINFO, "Testing epoll_ctl"); |
| last_result = PROTECT_FUNC(test_epoll_ctl, -1, epoll_fd); |
| if (last_result != 0) { |
| /* ctl test(s) failed */ |
| } |
| |
| tst_exit(); |
| } |
| |
| #else |
| |
| int main(void) |
| { |
| tst_brkm(TCONF, NULL, "No epoll support found."); |
| } |
| |
| #endif |