1/*-
2 * Copyright (c) 2024 Kyle Evans <kevans@FreeBSD.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <sys/types.h>
8#include <sys/ioctl.h>
9
10#include <termios.h>
11
12#include <atf-c.h>
13#include <libutil.h>
14
15/* Just a little more concise. */
16#define	newpty(masterp, slavep)	openpty((masterp), (slavep), NULL, NULL, NULL)
17
18ATF_TC_WITHOUT_HEAD(fionread);
19ATF_TC_BODY(fionread, tc)
20{
21	char rbuf[32];
22	char buf[] = "Hello";
23	int master, slave;
24	int bytes;
25
26	ATF_REQUIRE_EQ(0, newpty(&master, &slave));
27
28	/* Should be empty to begin with. */
29	ATF_REQUIRE_EQ(0, ioctl(master, FIONREAD, &bytes));
30	ATF_REQUIRE_EQ(0, bytes);
31
32	ATF_REQUIRE_EQ(sizeof(buf) - 1, write(slave, buf, sizeof(buf) - 1));
33	ATF_REQUIRE_EQ(0, ioctl(master, FIONREAD, &bytes));
34	ATF_REQUIRE_EQ(sizeof(buf) - 1, bytes);
35
36	/* Drain what we have available, should result in 0 bytes again. */
37	ATF_REQUIRE_EQ(sizeof(buf) - 1, read(master, rbuf, sizeof(rbuf)));
38	ATF_REQUIRE_EQ(0, ioctl(master, FIONREAD, &bytes));
39	ATF_REQUIRE_EQ(0, bytes);
40
41	/*
42	 * Write once more, then close the slave side with data still in the
43	 * buffer.
44	 */
45	ATF_REQUIRE_EQ(sizeof(buf) - 1, write(slave, buf, sizeof(buf) - 1));
46	ATF_REQUIRE_EQ(0, ioctl(master, FIONREAD, &bytes));
47	ATF_REQUIRE_EQ(sizeof(buf) - 1, bytes);
48
49	ATF_REQUIRE_EQ(0, close(slave));
50
51	/*
52	 * The tty's output queue is discarded upon close, so we shouldn't have
53	 * anything else to read().
54	 */
55	ATF_REQUIRE_EQ(0, ioctl(master, FIONREAD, &bytes));
56	ATF_REQUIRE_EQ(0, bytes);
57	ATF_REQUIRE_EQ(0, read(master, rbuf, sizeof(rbuf)));
58}
59
60ATF_TP_ADD_TCS(tp)
61{
62	ATF_TP_ADD_TC(tp, fionread);
63	return (atf_no_error());
64}
65