1/*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source.  A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12/*
13 * Copyright 2018 Joyent, Inc.
14 */
15
16/*
17 *        Test:	read.requeue
18 *   Assertion: A sequence of writes turns into a sequence of events.
19 *
20 *    Strategy: 1. Create a pipe
21 *		2. Call mevent_add() to be notified of writes to the pipe.  The
22 *		   callback will signal a cv.
23 *		3. In a loop, write to the pipe then wait on the cv.
24 */
25
26#include <errno.h>
27#include <fcntl.h>
28#include <pthread.h>
29#include <signal.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <strings.h>
33#include <unistd.h>
34
35#include <sys/types.h>
36#include <sys/stat.h>
37
38#include "testlib.h"
39#include "mevent.h"
40
41static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
42static pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
43
44static char *cookie = "Chocolate chip with fudge stripes";
45
46static void
47munch(int fd, enum ev_type ev, void *arg)
48{
49	static int i = 0;
50	char buf[8] = { 0 };
51	ssize_t nbytes;
52
53	ASSERT_INT_EQ(("bad event"), ev, EVF_READ);
54	ASSERT_PTR_EQ(("bad cookie"), arg, cookie);
55
56	if ((nbytes = read(fd, buf, sizeof (buf))) < 0) {
57		ASSERT_INT64_EQ(("bad read: %s", strerror(errno)), nbytes, 1);
58	}
59	VERBOSE(("read %ld bytes '%s'", nbytes, buf));
60
61	ASSERT_INT64_EQ(("wanted a byte of cookie"), nbytes, 1);
62
63	ASSERT_CHAR_EQ(("bad byte %d of cookie", i), buf[0], cookie[i]);
64
65	pthread_mutex_lock(&mtx);
66	pthread_cond_signal(&cv);
67	VERBOSE(("wakeup"));
68	pthread_mutex_unlock(&mtx);
69
70	i++;
71}
72
73int
74main(int argc, const char *argv[])
75{
76	int pipefds[2];
77	struct mevent *evp;
78
79	start_test(argv[0], 5);
80	start_event_thread();
81
82	if (pipe(pipefds) != 0) {
83		FAIL_ERRNO("pipe");
84	}
85	if (fcntl(pipefds[0], F_SETFL, O_NONBLOCK) != 0) {
86		FAIL_ERRNO("set pipe nonblocking");
87	}
88
89	evp = mevent_add(pipefds[0], EVF_READ, munch, cookie);
90	ASSERT_PTR_NEQ(("mevent_add"), evp, NULL);
91
92	for (int i = 0; cookie[i] != '\0'; i++) {
93		ssize_t written;
94
95		pthread_mutex_lock(&mtx);
96		written = write(pipefds[1], cookie + i, 1);
97		if (written < 0) {
98			FAIL_ERRNO("bad write");
99		}
100		ASSERT_INT64_EQ(("write byte %d of cookie", i), written, 1);
101
102		/* Wait for it to be read */
103		pthread_cond_wait(&cv, &mtx);
104		pthread_mutex_unlock(&mtx);
105	}
106
107	PASS();
108}
109