1/*
2 * Copyright (c) Crackerjack Project., 2007-2008 ,Hitachi, Ltd
3 *          Author(s): Takahiro Yasui <takahiro.yasui.mp@hitachi.com>,
4 *		       Yumiko Sugita <yumiko.sugita.yf@hitachi.com>,
5 *		       Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp>
6 * Copyright (c) 2016 Linux Test Project
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it would be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write the Free Software Foundation,
20 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21 */
22
23#include <limits.h>
24
25#include "lapi/syscalls.h"
26#include "tst_sig_proc.h"
27#include "tst_timer.h"
28#include "tst_test.h"
29
30static void sighandler(int sig LTP_ATTRIBUTE_UNUSED)
31{
32}
33
34enum test_type {
35	NORMAL,
36	SEND_SIGINT,
37};
38
39#define TYPE_NAME(x) .ttype = x, .desc = #x
40
41struct test_case {
42	clockid_t clk_id;	   /* clock_* clock type parameter */
43	int ttype;		   /* test type (enum) */
44	const char *desc;	   /* test description (name) */
45	int flags;		   /* clock_nanosleep flags parameter */
46	struct timespec rq;
47	int exp_ret;
48	int exp_err;
49};
50
51/*
52 *   test status of errors on man page
53 *   EINTR	      v (function was interrupted by a signal)
54 *   EINVAL	     v (invalid tv_nsec, etc.)
55 */
56
57static struct test_case tcase[] = {
58	{
59		TYPE_NAME(NORMAL),
60		.clk_id = CLOCK_REALTIME,
61		.flags = 0,
62		.rq = (struct timespec) {.tv_sec = 0, .tv_nsec = -1},
63		.exp_ret = EINVAL,
64		.exp_err = 0,
65	},
66	{
67		TYPE_NAME(NORMAL),
68		.clk_id = CLOCK_REALTIME,
69		.flags = 0,
70		.rq = (struct timespec) {.tv_sec = 0, .tv_nsec = 1000000000},
71		.exp_ret = EINVAL,
72		.exp_err = 0,
73	},
74	{
75		TYPE_NAME(NORMAL),
76		.clk_id = CLOCK_THREAD_CPUTIME_ID,
77		.flags = 0,
78		.rq = (struct timespec) {.tv_sec = 0, .tv_nsec = 500000000},
79		.exp_ret = EINVAL,
80		.exp_err = 0,
81	},
82	{
83		TYPE_NAME(SEND_SIGINT),
84		.clk_id = CLOCK_REALTIME,
85		.flags = 0,
86		.rq = (struct timespec) {.tv_sec = 10, .tv_nsec = 0},
87		.exp_ret = EINTR,
88		.exp_err = 0,
89	},
90};
91
92void setup(void)
93{
94	SAFE_SIGNAL(SIGINT, sighandler);
95}
96
97static void do_test(unsigned int i)
98{
99	struct test_case *tc = &tcase[i];
100	struct timespec rm = {0};
101	pid_t pid = 0;
102
103	tst_res(TINFO, "case %s", tc->desc);
104
105	if (tc->ttype == SEND_SIGINT)
106		pid = create_sig_proc(SIGINT, 40, 500000);
107
108	TEST(clock_nanosleep(tc->clk_id, tc->flags, &tc->rq, &rm));
109
110	if (pid) {
111		SAFE_KILL(pid, SIGTERM);
112		SAFE_WAIT(NULL);
113	}
114
115	if (tc->ttype == SEND_SIGINT) {
116		long long expect_ms = tst_timespec_to_ms(tc->rq);
117		long long remain_ms = tst_timespec_to_ms(rm);
118
119		tst_res(TINFO, "remain time: %lds %ldns", rm.tv_sec, rm.tv_nsec);
120
121		if (!rm.tv_sec && !rm.tv_nsec) {
122			tst_res(TFAIL | TTERRNO,
123				"The clock_nanosleep() haven't updated"
124				" timestamp with remaining time");
125			return;
126		}
127
128		if (remain_ms > expect_ms) {
129			tst_res(TFAIL| TTERRNO,
130				"remaining time > requested time (%lld > %lld)",
131				remain_ms, expect_ms);
132			return;
133		}
134	}
135
136	if (TEST_RETURN != tc->exp_ret) {
137		tst_res(TFAIL | TTERRNO, "returned %ld, expected %d,"
138			" expected errno: %s (%d)", TEST_RETURN,
139			tc->exp_ret, tst_strerrno(tc->exp_err), tc->exp_err);
140		return;
141	}
142
143	tst_res(TPASS, "returned %s (%ld)",
144		tst_strerrno(TEST_RETURN), TEST_RETURN);
145}
146
147static struct tst_test test = {
148	.tcnt = ARRAY_SIZE(tcase),
149	.test = do_test,
150	.setup = setup,
151	.forks_child = 1,
152};
153