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