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