t_nanosleep.c revision 314817
1/* $NetBSD: t_nanosleep.c,v 1.4 2017/01/13 21:15:14 christos Exp $ */
2
3/*-
4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jukka Ruohonen.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31#include <sys/cdefs.h>
32__RCSID("$NetBSD: t_nanosleep.c,v 1.4 2017/01/13 21:15:14 christos Exp $");
33
34#include <sys/time.h>
35#include <sys/wait.h>
36
37#include <atf-c.h>
38#include <errno.h>
39#include <time.h>
40#include <signal.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <sysexits.h>
45#include <unistd.h>
46
47static void
48handler(int signo __unused)
49{
50	/* Nothing. */
51}
52
53ATF_TC(nanosleep_basic);
54ATF_TC_HEAD(nanosleep_basic, tc)
55{
56	atf_tc_set_md_var(tc, "descr", "Test that nanosleep(2) works");
57}
58
59ATF_TC_BODY(nanosleep_basic, tc)
60{
61	static const size_t maxiter = 10;
62	struct timespec ts1, ts2, tsn;
63	size_t i;
64
65	for (i = 1; i < maxiter; i++) {
66
67		tsn.tv_sec = 0;
68		tsn.tv_nsec = i;
69
70		(void)memset(&ts1, 0, sizeof(struct timespec));
71		(void)memset(&ts2, 0, sizeof(struct timespec));
72
73		ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts1) == 0);
74		ATF_REQUIRE(nanosleep(&tsn, NULL) == 0);
75		ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts2) == 0);
76
77		/*
78		 * Verify that we slept at least one nanosecond.
79		 */
80		if (timespeccmp(&ts2, &ts1, <=) != 0) {
81
82			(void)fprintf(stderr,
83			    "sleep time:: sec %llu, nsec %lu\n\t\t"
84			    "ts1: sec %llu, nsec %lu\n\t\t"
85			    "ts2: sec %llu, nsec %lu\n",
86			    (unsigned long long)tsn.tv_sec, tsn.tv_nsec,
87			    (unsigned long long)ts1.tv_sec, ts1.tv_nsec,
88			    (unsigned long long)ts2.tv_sec, ts2.tv_nsec);
89
90			atf_tc_fail_nonfatal("inaccuracies in sleep time "
91			    "(resolution = %lu nsec)", tsn.tv_nsec);
92		}
93	}
94}
95
96ATF_TC(nanosleep_err);
97ATF_TC_HEAD(nanosleep_err, tc)
98{
99	atf_tc_set_md_var(tc, "descr",
100	    "Test errors from nanosleep(2) (PR bin/14558)");
101}
102
103ATF_TC_BODY(nanosleep_err, tc)
104{
105	struct timespec ts;
106
107	ts.tv_sec = 1;
108	ts.tv_nsec = -1;
109	errno = 0;
110	ATF_REQUIRE_ERRNO(EINVAL, nanosleep(&ts, NULL) == -1);
111
112	ts.tv_sec = 1;
113	ts.tv_nsec = 1000000000;
114	errno = 0;
115	ATF_REQUIRE_ERRNO(EINVAL, nanosleep(&ts, NULL) == -1);
116
117	ts.tv_sec = -1;
118	ts.tv_nsec = 0;
119	errno = 0;
120	ATF_REQUIRE_ERRNO(0, nanosleep(&ts, NULL) == 0);
121
122	errno = 0;
123	ATF_REQUIRE_ERRNO(EFAULT, nanosleep((void *)-1, NULL) == -1);
124}
125
126ATF_TC(nanosleep_sig);
127ATF_TC_HEAD(nanosleep_sig, tc)
128{
129	atf_tc_set_md_var(tc, "descr", "Test signal for nanosleep(2)");
130}
131
132ATF_TC_BODY(nanosleep_sig, tc)
133{
134	struct timespec tsn, tsr;
135	pid_t pid;
136	int sta;
137
138	/*
139	 * Test that a signal interrupts nanosleep(2).
140	 *
141	 * (In which case the return value should be -1 and the
142	 * second parameter should contain the unslept time.)
143	 */
144	pid = fork();
145
146	ATF_REQUIRE(pid >= 0);
147	ATF_REQUIRE(signal(SIGINT, handler) == 0);
148
149	if (pid == 0) {
150
151		tsn.tv_sec = 10;
152		tsn.tv_nsec = 0;
153
154		tsr.tv_sec = 0;
155		tsr.tv_nsec = 0;
156
157		errno = 0;
158
159		if (nanosleep(&tsn, &tsr) != -1)
160			_exit(EXIT_FAILURE);
161
162		if (errno != EINTR)
163			_exit(EXIT_FAILURE);
164
165		if (tsr.tv_sec == 0 && tsr.tv_nsec == 0)
166			_exit(EXIT_FAILURE);
167
168		_exit(EXIT_SUCCESS);
169	}
170
171	(void)sleep(1);
172	(void)kill(pid, SIGINT);
173	(void)wait(&sta);
174
175	if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
176		atf_tc_fail("signal did not interrupt nanosleep(2)");
177}
178
179ATF_TP_ADD_TCS(tp)
180{
181
182	ATF_TP_ADD_TC(tp, nanosleep_basic);
183	ATF_TP_ADD_TC(tp, nanosleep_err);
184	ATF_TP_ADD_TC(tp, nanosleep_sig);
185
186	return atf_no_error();
187}
188