#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "testlib.h"
#include "mevent.h"
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
static int
get_count(void)
{
int global = -1, change = -1, del_pending = -1;
int total;
test_mevent_count_lists(&global, &change, &del_pending);
ASSERT_INT_NEQ(("count not set"), global, -1);
ASSERT_INT_NEQ(("count not set"), change, -1);
ASSERT_INT_NEQ(("count not set"), change, -1);
ASSERT_INT_EQ(("pending delete not processed"), del_pending, 0);
total = global + change + del_pending;
VERBOSE(("count = %d (%d + %d + %d)", total, global, change,
del_pending));
return (total);
}
static void
not_called_cb(int fd, enum ev_type ev, void *arg)
{
FAIL(("this callback should never be called"));
}
static void
flush_cb(int fd, enum ev_type ev, void *arg)
{
char buf[32];
while (read(fd, buf, sizeof (buf)) > 0)
;
pthread_mutex_lock(&mtx);
pthread_cond_signal(&cv);
pthread_mutex_unlock(&mtx);
}
void
flush_and_wait(int fd)
{
uint8_t msg = 42;
pthread_mutex_lock(&mtx);
if (write(fd, &msg, sizeof (msg)) != sizeof (msg)) {
FAIL(("bad write"));
}
pthread_cond_wait(&cv, &mtx);
pthread_mutex_unlock(&mtx);
}
int
main(int argc, const char *argv[])
{
int unused_pipe[2];
int flush_pipe[2];
struct mevent *unused_evp, *flush_evp;
int count1, count2;
start_test(argv[0], 5);
start_event_thread();
if (pipe(unused_pipe) != 0) {
FAIL_ERRNO("pipe");
}
VERBOSE(("unused_pipe[] = { %d, %d }", unused_pipe[0], unused_pipe[1]));
if (fcntl(unused_pipe[0], F_SETFL, O_NONBLOCK) != 0) {
FAIL_ERRNO("set pipe nonblocking");
}
unused_evp = mevent_add(unused_pipe[0], EVF_READ, not_called_cb, NULL);
ASSERT_PTR_NEQ(("mevent_add"), unused_evp, NULL);
if (pipe(flush_pipe) != 0) {
FAIL_ERRNO("pipe");
}
VERBOSE(("flush_pipe[] = { %d, %d }", flush_pipe[0],
flush_pipe[1]));
if (fcntl(flush_pipe[0], F_SETFL, O_NONBLOCK) != 0) {
FAIL_ERRNO("set pipe nonblocking");
}
flush_evp = mevent_add(flush_pipe[0], EVF_READ, flush_cb, NULL);
ASSERT_PTR_NEQ(("mevent_add"), flush_evp, NULL);
flush_and_wait(flush_pipe[1]);
count1 = get_count();
if (mevent_delete(unused_evp) != 0) {
FAIL_ERRNO("mevent_delete");
}
flush_and_wait(flush_pipe[1]);
count2 = get_count();
if (count1 - 1 != count2) {
FAIL(("mevent_delete() did not decrease count by 1: "
"was %d, now %d", count1, count2));
}
PASS();
}