xref: /linux/tools/testing/selftests/timers/valid-adjtimex.c (revision 621cde16e49b3ecf7d59a8106a20aaebfb4a59a9)
1de52133fSJohn Stultz /* valid adjtimex test
2de52133fSJohn Stultz  *              by: John Stultz <john.stultz@linaro.org>
3de52133fSJohn Stultz  *              (C) Copyright Linaro 2015
4de52133fSJohn Stultz  *              Licensed under the GPLv2
5de52133fSJohn Stultz  *
6de52133fSJohn Stultz  *  This test validates adjtimex interface with valid
7de52133fSJohn Stultz  *  and invalid test data.
8de52133fSJohn Stultz  *
9de52133fSJohn Stultz  *  Usage: valid-adjtimex
10de52133fSJohn Stultz  *
11de52133fSJohn Stultz  *  To build:
12de52133fSJohn Stultz  *	$ gcc valid-adjtimex.c -o valid-adjtimex -lrt
13de52133fSJohn Stultz  *
14de52133fSJohn Stultz  *   This program is free software: you can redistribute it and/or modify
15de52133fSJohn Stultz  *   it under the terms of the GNU General Public License as published by
16de52133fSJohn Stultz  *   the Free Software Foundation, either version 2 of the License, or
17de52133fSJohn Stultz  *   (at your option) any later version.
18de52133fSJohn Stultz  *
19de52133fSJohn Stultz  *   This program is distributed in the hope that it will be useful,
20de52133fSJohn Stultz  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
21de52133fSJohn Stultz  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22de52133fSJohn Stultz  *   GNU General Public License for more details.
23de52133fSJohn Stultz  */
24de52133fSJohn Stultz #include <stdio.h>
25de52133fSJohn Stultz #include <stdlib.h>
26de52133fSJohn Stultz #include <time.h>
27de52133fSJohn Stultz #include <sys/time.h>
28de52133fSJohn Stultz #include <sys/timex.h>
29de52133fSJohn Stultz #include <string.h>
30de52133fSJohn Stultz #include <signal.h>
31de52133fSJohn Stultz #include <unistd.h>
32de52133fSJohn Stultz #include "../kselftest.h"
33de52133fSJohn Stultz 
34e03a58c3SJohn Stultz #define NSEC_PER_SEC 1000000000LL
35e03a58c3SJohn Stultz #define USEC_PER_SEC 1000000LL
36e03a58c3SJohn Stultz 
37e03a58c3SJohn Stultz #define ADJ_SETOFFSET 0x0100
38e03a58c3SJohn Stultz 
39e03a58c3SJohn Stultz #include <sys/syscall.h>
clock_adjtime(clockid_t id,struct timex * tx)409a162977SWolfram Sang int clock_adjtime(clockid_t id, struct timex *tx)
41e03a58c3SJohn Stultz {
42e03a58c3SJohn Stultz 	return syscall(__NR_clock_adjtime, id, tx);
43e03a58c3SJohn Stultz }
44e03a58c3SJohn Stultz 
45de52133fSJohn Stultz 
46de52133fSJohn Stultz /* clear NTP time_status & time_state */
clear_time_state(void)47de52133fSJohn Stultz int clear_time_state(void)
48de52133fSJohn Stultz {
49de52133fSJohn Stultz 	struct timex tx;
50de52133fSJohn Stultz 	int ret;
51de52133fSJohn Stultz 
52de52133fSJohn Stultz 	tx.modes = ADJ_STATUS;
53de52133fSJohn Stultz 	tx.status = 0;
54de52133fSJohn Stultz 	ret = adjtimex(&tx);
55de52133fSJohn Stultz 	return ret;
56de52133fSJohn Stultz }
57de52133fSJohn Stultz 
58de52133fSJohn Stultz #define NUM_FREQ_VALID 32
59de52133fSJohn Stultz #define NUM_FREQ_OUTOFRANGE 4
60de52133fSJohn Stultz #define NUM_FREQ_INVALID 2
61de52133fSJohn Stultz 
6207636136SJohn Stultz #define SHIFTED_PPM (1 << 16)
6307636136SJohn Stultz 
64de52133fSJohn Stultz long valid_freq[NUM_FREQ_VALID] = {
6507636136SJohn Stultz 	 -499 * SHIFTED_PPM,
6607636136SJohn Stultz 	 -450 * SHIFTED_PPM,
6707636136SJohn Stultz 	 -400 * SHIFTED_PPM,
6807636136SJohn Stultz 	 -350 * SHIFTED_PPM,
6907636136SJohn Stultz 	 -300 * SHIFTED_PPM,
7007636136SJohn Stultz 	 -250 * SHIFTED_PPM,
7107636136SJohn Stultz 	 -200 * SHIFTED_PPM,
7207636136SJohn Stultz 	 -150 * SHIFTED_PPM,
7307636136SJohn Stultz 	 -100 * SHIFTED_PPM,
7407636136SJohn Stultz 	  -75 * SHIFTED_PPM,
7507636136SJohn Stultz 	  -50 * SHIFTED_PPM,
7607636136SJohn Stultz 	  -25 * SHIFTED_PPM,
7707636136SJohn Stultz 	  -10 * SHIFTED_PPM,
7807636136SJohn Stultz 	   -5 * SHIFTED_PPM,
7907636136SJohn Stultz 	   -1 * SHIFTED_PPM,
80de52133fSJohn Stultz 	-1000,
8107636136SJohn Stultz 	    1 * SHIFTED_PPM,
8207636136SJohn Stultz 	    5 * SHIFTED_PPM,
8307636136SJohn Stultz 	   10 * SHIFTED_PPM,
8407636136SJohn Stultz 	   25 * SHIFTED_PPM,
8507636136SJohn Stultz 	   50 * SHIFTED_PPM,
8607636136SJohn Stultz 	   75 * SHIFTED_PPM,
8707636136SJohn Stultz 	  100 * SHIFTED_PPM,
8807636136SJohn Stultz 	  150 * SHIFTED_PPM,
8907636136SJohn Stultz 	  200 * SHIFTED_PPM,
9007636136SJohn Stultz 	  250 * SHIFTED_PPM,
9107636136SJohn Stultz 	  300 * SHIFTED_PPM,
9207636136SJohn Stultz 	  350 * SHIFTED_PPM,
9307636136SJohn Stultz 	  400 * SHIFTED_PPM,
9407636136SJohn Stultz 	  450 * SHIFTED_PPM,
9507636136SJohn Stultz 	  499 * SHIFTED_PPM,
96de52133fSJohn Stultz };
97de52133fSJohn Stultz 
98de52133fSJohn Stultz long outofrange_freq[NUM_FREQ_OUTOFRANGE] = {
9907636136SJohn Stultz 	-1000 * SHIFTED_PPM,
10007636136SJohn Stultz 	 -550 * SHIFTED_PPM,
10107636136SJohn Stultz 	  550 * SHIFTED_PPM,
10207636136SJohn Stultz 	 1000 * SHIFTED_PPM,
103de52133fSJohn Stultz };
104de52133fSJohn Stultz 
105de52133fSJohn Stultz #define LONG_MAX (~0UL>>1)
106de52133fSJohn Stultz #define LONG_MIN (-LONG_MAX - 1)
107de52133fSJohn Stultz 
108de52133fSJohn Stultz long invalid_freq[NUM_FREQ_INVALID] = {
109de52133fSJohn Stultz 	LONG_MAX,
110de52133fSJohn Stultz 	LONG_MIN,
111de52133fSJohn Stultz };
112de52133fSJohn Stultz 
validate_freq(void)113de52133fSJohn Stultz int validate_freq(void)
114de52133fSJohn Stultz {
115de52133fSJohn Stultz 	struct timex tx;
116de52133fSJohn Stultz 	int ret, pass = 0;
117de52133fSJohn Stultz 	int i;
118de52133fSJohn Stultz 
119de52133fSJohn Stultz 	clear_time_state();
120de52133fSJohn Stultz 
121de52133fSJohn Stultz 	memset(&tx, 0, sizeof(struct timex));
122de52133fSJohn Stultz 	/* Set the leap second insert flag */
123de52133fSJohn Stultz 
124de52133fSJohn Stultz 	printf("Testing ADJ_FREQ... ");
125fe483192SKees Cook 	fflush(stdout);
126de52133fSJohn Stultz 	for (i = 0; i < NUM_FREQ_VALID; i++) {
127de52133fSJohn Stultz 		tx.modes = ADJ_FREQUENCY;
128de52133fSJohn Stultz 		tx.freq = valid_freq[i];
129de52133fSJohn Stultz 
130de52133fSJohn Stultz 		ret = adjtimex(&tx);
131de52133fSJohn Stultz 		if (ret < 0) {
132de52133fSJohn Stultz 			printf("[FAIL]\n");
133de52133fSJohn Stultz 			printf("Error: adjtimex(ADJ_FREQ, %ld - %ld ppm\n",
134de52133fSJohn Stultz 				valid_freq[i], valid_freq[i]>>16);
135de52133fSJohn Stultz 			pass = -1;
136de52133fSJohn Stultz 			goto out;
137de52133fSJohn Stultz 		}
138de52133fSJohn Stultz 		tx.modes = 0;
139de52133fSJohn Stultz 		ret = adjtimex(&tx);
140de52133fSJohn Stultz 		if (tx.freq != valid_freq[i]) {
141de52133fSJohn Stultz 			printf("Warning: freq value %ld not what we set it (%ld)!\n",
142de52133fSJohn Stultz 					tx.freq, valid_freq[i]);
143de52133fSJohn Stultz 		}
144de52133fSJohn Stultz 	}
145de52133fSJohn Stultz 	for (i = 0; i < NUM_FREQ_OUTOFRANGE; i++) {
146de52133fSJohn Stultz 		tx.modes = ADJ_FREQUENCY;
147de52133fSJohn Stultz 		tx.freq = outofrange_freq[i];
148de52133fSJohn Stultz 
149de52133fSJohn Stultz 		ret = adjtimex(&tx);
150de52133fSJohn Stultz 		if (ret < 0) {
151de52133fSJohn Stultz 			printf("[FAIL]\n");
152de52133fSJohn Stultz 			printf("Error: adjtimex(ADJ_FREQ, %ld - %ld ppm\n",
153de52133fSJohn Stultz 				outofrange_freq[i], outofrange_freq[i]>>16);
154de52133fSJohn Stultz 			pass = -1;
155de52133fSJohn Stultz 			goto out;
156de52133fSJohn Stultz 		}
157de52133fSJohn Stultz 		tx.modes = 0;
158de52133fSJohn Stultz 		ret = adjtimex(&tx);
159de52133fSJohn Stultz 		if (tx.freq == outofrange_freq[i]) {
160de52133fSJohn Stultz 			printf("[FAIL]\n");
161de52133fSJohn Stultz 			printf("ERROR: out of range value %ld actually set!\n",
162de52133fSJohn Stultz 					tx.freq);
163de52133fSJohn Stultz 			pass = -1;
164de52133fSJohn Stultz 			goto out;
165de52133fSJohn Stultz 		}
166de52133fSJohn Stultz 	}
167de52133fSJohn Stultz 
168de52133fSJohn Stultz 
169de52133fSJohn Stultz 	if (sizeof(long) == 8) { /* this case only applies to 64bit systems */
170de52133fSJohn Stultz 		for (i = 0; i < NUM_FREQ_INVALID; i++) {
171de52133fSJohn Stultz 			tx.modes = ADJ_FREQUENCY;
172de52133fSJohn Stultz 			tx.freq = invalid_freq[i];
173de52133fSJohn Stultz 			ret = adjtimex(&tx);
174de52133fSJohn Stultz 			if (ret >= 0) {
175de52133fSJohn Stultz 				printf("[FAIL]\n");
176de52133fSJohn Stultz 				printf("Error: No failure on invalid ADJ_FREQUENCY %ld\n",
177de52133fSJohn Stultz 					invalid_freq[i]);
178de52133fSJohn Stultz 				pass = -1;
179de52133fSJohn Stultz 				goto out;
180de52133fSJohn Stultz 			}
181de52133fSJohn Stultz 		}
182de52133fSJohn Stultz 	}
183de52133fSJohn Stultz 
184de52133fSJohn Stultz 	printf("[OK]\n");
185de52133fSJohn Stultz out:
186de52133fSJohn Stultz 	/* reset freq to zero */
187de52133fSJohn Stultz 	tx.modes = ADJ_FREQUENCY;
188de52133fSJohn Stultz 	tx.freq = 0;
189de52133fSJohn Stultz 	ret = adjtimex(&tx);
190de52133fSJohn Stultz 
191de52133fSJohn Stultz 	return pass;
192de52133fSJohn Stultz }
193de52133fSJohn Stultz 
194de52133fSJohn Stultz 
set_offset(long long offset,int use_nano)195e03a58c3SJohn Stultz int set_offset(long long offset, int use_nano)
196e03a58c3SJohn Stultz {
197e03a58c3SJohn Stultz 	struct timex tmx = {};
198e03a58c3SJohn Stultz 	int ret;
199e03a58c3SJohn Stultz 
200e03a58c3SJohn Stultz 	tmx.modes = ADJ_SETOFFSET;
201e03a58c3SJohn Stultz 	if (use_nano) {
202e03a58c3SJohn Stultz 		tmx.modes |= ADJ_NANO;
203e03a58c3SJohn Stultz 
204e03a58c3SJohn Stultz 		tmx.time.tv_sec = offset / NSEC_PER_SEC;
205e03a58c3SJohn Stultz 		tmx.time.tv_usec = offset % NSEC_PER_SEC;
206e03a58c3SJohn Stultz 
207e03a58c3SJohn Stultz 		if (offset < 0 && tmx.time.tv_usec) {
208e03a58c3SJohn Stultz 			tmx.time.tv_sec -= 1;
209e03a58c3SJohn Stultz 			tmx.time.tv_usec += NSEC_PER_SEC;
210e03a58c3SJohn Stultz 		}
211e03a58c3SJohn Stultz 	} else {
212e03a58c3SJohn Stultz 		tmx.time.tv_sec = offset / USEC_PER_SEC;
213e03a58c3SJohn Stultz 		tmx.time.tv_usec = offset % USEC_PER_SEC;
214e03a58c3SJohn Stultz 
215e03a58c3SJohn Stultz 		if (offset < 0 && tmx.time.tv_usec) {
216e03a58c3SJohn Stultz 			tmx.time.tv_sec -= 1;
217e03a58c3SJohn Stultz 			tmx.time.tv_usec += USEC_PER_SEC;
218e03a58c3SJohn Stultz 		}
219e03a58c3SJohn Stultz 	}
220e03a58c3SJohn Stultz 
221e03a58c3SJohn Stultz 	ret = clock_adjtime(CLOCK_REALTIME, &tmx);
222e03a58c3SJohn Stultz 	if (ret < 0) {
223e03a58c3SJohn Stultz 		printf("(sec: %ld  usec: %ld) ", tmx.time.tv_sec, tmx.time.tv_usec);
224e03a58c3SJohn Stultz 		printf("[FAIL]\n");
225e03a58c3SJohn Stultz 		return -1;
226e03a58c3SJohn Stultz 	}
227e03a58c3SJohn Stultz 	return 0;
228e03a58c3SJohn Stultz }
229e03a58c3SJohn Stultz 
set_bad_offset(long sec,long usec,int use_nano)230e03a58c3SJohn Stultz int set_bad_offset(long sec, long usec, int use_nano)
231e03a58c3SJohn Stultz {
232e03a58c3SJohn Stultz 	struct timex tmx = {};
233e03a58c3SJohn Stultz 	int ret;
234e03a58c3SJohn Stultz 
235e03a58c3SJohn Stultz 	tmx.modes = ADJ_SETOFFSET;
236e03a58c3SJohn Stultz 	if (use_nano)
237e03a58c3SJohn Stultz 		tmx.modes |= ADJ_NANO;
238e03a58c3SJohn Stultz 
239e03a58c3SJohn Stultz 	tmx.time.tv_sec = sec;
240e03a58c3SJohn Stultz 	tmx.time.tv_usec = usec;
241e03a58c3SJohn Stultz 	ret = clock_adjtime(CLOCK_REALTIME, &tmx);
242e03a58c3SJohn Stultz 	if (ret >= 0) {
243e03a58c3SJohn Stultz 		printf("Invalid (sec: %ld  usec: %ld) did not fail! ", tmx.time.tv_sec, tmx.time.tv_usec);
244e03a58c3SJohn Stultz 		printf("[FAIL]\n");
245e03a58c3SJohn Stultz 		return -1;
246e03a58c3SJohn Stultz 	}
247e03a58c3SJohn Stultz 	return 0;
248e03a58c3SJohn Stultz }
249e03a58c3SJohn Stultz 
validate_set_offset(void)250e03a58c3SJohn Stultz int validate_set_offset(void)
251e03a58c3SJohn Stultz {
252e03a58c3SJohn Stultz 	printf("Testing ADJ_SETOFFSET... ");
253fe483192SKees Cook 	fflush(stdout);
254e03a58c3SJohn Stultz 
255e03a58c3SJohn Stultz 	/* Test valid values */
256e03a58c3SJohn Stultz 	if (set_offset(NSEC_PER_SEC - 1, 1))
257e03a58c3SJohn Stultz 		return -1;
258e03a58c3SJohn Stultz 
259e03a58c3SJohn Stultz 	if (set_offset(-NSEC_PER_SEC + 1, 1))
260e03a58c3SJohn Stultz 		return -1;
261e03a58c3SJohn Stultz 
262e03a58c3SJohn Stultz 	if (set_offset(-NSEC_PER_SEC - 1, 1))
263e03a58c3SJohn Stultz 		return -1;
264e03a58c3SJohn Stultz 
265e03a58c3SJohn Stultz 	if (set_offset(5 * NSEC_PER_SEC, 1))
266e03a58c3SJohn Stultz 		return -1;
267e03a58c3SJohn Stultz 
268e03a58c3SJohn Stultz 	if (set_offset(-5 * NSEC_PER_SEC, 1))
269e03a58c3SJohn Stultz 		return -1;
270e03a58c3SJohn Stultz 
271e03a58c3SJohn Stultz 	if (set_offset(5 * NSEC_PER_SEC + NSEC_PER_SEC / 2, 1))
272e03a58c3SJohn Stultz 		return -1;
273e03a58c3SJohn Stultz 
274e03a58c3SJohn Stultz 	if (set_offset(-5 * NSEC_PER_SEC - NSEC_PER_SEC / 2, 1))
275e03a58c3SJohn Stultz 		return -1;
276e03a58c3SJohn Stultz 
277e03a58c3SJohn Stultz 	if (set_offset(USEC_PER_SEC - 1, 0))
278e03a58c3SJohn Stultz 		return -1;
279e03a58c3SJohn Stultz 
280e03a58c3SJohn Stultz 	if (set_offset(-USEC_PER_SEC + 1, 0))
281e03a58c3SJohn Stultz 		return -1;
282e03a58c3SJohn Stultz 
283e03a58c3SJohn Stultz 	if (set_offset(-USEC_PER_SEC - 1, 0))
284e03a58c3SJohn Stultz 		return -1;
285e03a58c3SJohn Stultz 
286e03a58c3SJohn Stultz 	if (set_offset(5 * USEC_PER_SEC, 0))
287e03a58c3SJohn Stultz 		return -1;
288e03a58c3SJohn Stultz 
289e03a58c3SJohn Stultz 	if (set_offset(-5 * USEC_PER_SEC, 0))
290e03a58c3SJohn Stultz 		return -1;
291e03a58c3SJohn Stultz 
292e03a58c3SJohn Stultz 	if (set_offset(5 * USEC_PER_SEC + USEC_PER_SEC / 2, 0))
293e03a58c3SJohn Stultz 		return -1;
294e03a58c3SJohn Stultz 
295e03a58c3SJohn Stultz 	if (set_offset(-5 * USEC_PER_SEC - USEC_PER_SEC / 2, 0))
296e03a58c3SJohn Stultz 		return -1;
297e03a58c3SJohn Stultz 
298e03a58c3SJohn Stultz 	/* Test invalid values */
299e03a58c3SJohn Stultz 	if (set_bad_offset(0, -1, 1))
300e03a58c3SJohn Stultz 		return -1;
301e03a58c3SJohn Stultz 	if (set_bad_offset(0, -1, 0))
302e03a58c3SJohn Stultz 		return -1;
303e03a58c3SJohn Stultz 	if (set_bad_offset(0, 2 * NSEC_PER_SEC, 1))
304e03a58c3SJohn Stultz 		return -1;
305e03a58c3SJohn Stultz 	if (set_bad_offset(0, 2 * USEC_PER_SEC, 0))
306e03a58c3SJohn Stultz 		return -1;
307e03a58c3SJohn Stultz 	if (set_bad_offset(0, NSEC_PER_SEC, 1))
308e03a58c3SJohn Stultz 		return -1;
309e03a58c3SJohn Stultz 	if (set_bad_offset(0, USEC_PER_SEC, 0))
310e03a58c3SJohn Stultz 		return -1;
311e03a58c3SJohn Stultz 	if (set_bad_offset(0, -NSEC_PER_SEC, 1))
312e03a58c3SJohn Stultz 		return -1;
313e03a58c3SJohn Stultz 	if (set_bad_offset(0, -USEC_PER_SEC, 0))
314e03a58c3SJohn Stultz 		return -1;
315e03a58c3SJohn Stultz 
316e03a58c3SJohn Stultz 	printf("[OK]\n");
317e03a58c3SJohn Stultz 	return 0;
318e03a58c3SJohn Stultz }
319e03a58c3SJohn Stultz 
main(int argc,char ** argv)320de52133fSJohn Stultz int main(int argc, char **argv)
321de52133fSJohn Stultz {
322de52133fSJohn Stultz 	if (validate_freq())
323*bc7e5d23SNathan Chancellor 		ksft_exit_fail();
324de52133fSJohn Stultz 
325e03a58c3SJohn Stultz 	if (validate_set_offset())
326*bc7e5d23SNathan Chancellor 		ksft_exit_fail();
327e03a58c3SJohn Stultz 
328*bc7e5d23SNathan Chancellor 	ksft_exit_pass();
329de52133fSJohn Stultz }
330