Back to home page

OSCL-LXR

 
 

    


0001 /* valid adjtimex test
0002  *              by: John Stultz <john.stultz@linaro.org>
0003  *              (C) Copyright Linaro 2015
0004  *              Licensed under the GPLv2
0005  *
0006  *  This test validates adjtimex interface with valid
0007  *  and invalid test data.
0008  *
0009  *  Usage: valid-adjtimex
0010  *
0011  *  To build:
0012  *  $ gcc valid-adjtimex.c -o valid-adjtimex -lrt
0013  *
0014  *   This program is free software: you can redistribute it and/or modify
0015  *   it under the terms of the GNU General Public License as published by
0016  *   the Free Software Foundation, either version 2 of the License, or
0017  *   (at your option) any later version.
0018  *
0019  *   This program is distributed in the hope that it will be useful,
0020  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
0021  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0022  *   GNU General Public License for more details.
0023  */
0024 
0025 
0026 
0027 #include <stdio.h>
0028 #include <stdlib.h>
0029 #include <time.h>
0030 #include <sys/time.h>
0031 #include <sys/timex.h>
0032 #include <string.h>
0033 #include <signal.h>
0034 #include <unistd.h>
0035 #include "../kselftest.h"
0036 
0037 #define NSEC_PER_SEC 1000000000LL
0038 #define USEC_PER_SEC 1000000LL
0039 
0040 #define ADJ_SETOFFSET 0x0100
0041 
0042 #include <sys/syscall.h>
0043 int clock_adjtime(clockid_t id, struct timex *tx)
0044 {
0045     return syscall(__NR_clock_adjtime, id, tx);
0046 }
0047 
0048 
0049 /* clear NTP time_status & time_state */
0050 int clear_time_state(void)
0051 {
0052     struct timex tx;
0053     int ret;
0054 
0055     tx.modes = ADJ_STATUS;
0056     tx.status = 0;
0057     ret = adjtimex(&tx);
0058     return ret;
0059 }
0060 
0061 #define NUM_FREQ_VALID 32
0062 #define NUM_FREQ_OUTOFRANGE 4
0063 #define NUM_FREQ_INVALID 2
0064 
0065 long valid_freq[NUM_FREQ_VALID] = {
0066     -499<<16,
0067     -450<<16,
0068     -400<<16,
0069     -350<<16,
0070     -300<<16,
0071     -250<<16,
0072     -200<<16,
0073     -150<<16,
0074     -100<<16,
0075     -75<<16,
0076     -50<<16,
0077     -25<<16,
0078     -10<<16,
0079     -5<<16,
0080     -1<<16,
0081     -1000,
0082     1<<16,
0083     5<<16,
0084     10<<16,
0085     25<<16,
0086     50<<16,
0087     75<<16,
0088     100<<16,
0089     150<<16,
0090     200<<16,
0091     250<<16,
0092     300<<16,
0093     350<<16,
0094     400<<16,
0095     450<<16,
0096     499<<16,
0097 };
0098 
0099 long outofrange_freq[NUM_FREQ_OUTOFRANGE] = {
0100     -1000<<16,
0101     -550<<16,
0102     550<<16,
0103     1000<<16,
0104 };
0105 
0106 #define LONG_MAX (~0UL>>1)
0107 #define LONG_MIN (-LONG_MAX - 1)
0108 
0109 long invalid_freq[NUM_FREQ_INVALID] = {
0110     LONG_MAX,
0111     LONG_MIN,
0112 };
0113 
0114 int validate_freq(void)
0115 {
0116     struct timex tx;
0117     int ret, pass = 0;
0118     int i;
0119 
0120     clear_time_state();
0121 
0122     memset(&tx, 0, sizeof(struct timex));
0123     /* Set the leap second insert flag */
0124 
0125     printf("Testing ADJ_FREQ... ");
0126     fflush(stdout);
0127     for (i = 0; i < NUM_FREQ_VALID; i++) {
0128         tx.modes = ADJ_FREQUENCY;
0129         tx.freq = valid_freq[i];
0130 
0131         ret = adjtimex(&tx);
0132         if (ret < 0) {
0133             printf("[FAIL]\n");
0134             printf("Error: adjtimex(ADJ_FREQ, %ld - %ld ppm\n",
0135                 valid_freq[i], valid_freq[i]>>16);
0136             pass = -1;
0137             goto out;
0138         }
0139         tx.modes = 0;
0140         ret = adjtimex(&tx);
0141         if (tx.freq != valid_freq[i]) {
0142             printf("Warning: freq value %ld not what we set it (%ld)!\n",
0143                     tx.freq, valid_freq[i]);
0144         }
0145     }
0146     for (i = 0; i < NUM_FREQ_OUTOFRANGE; i++) {
0147         tx.modes = ADJ_FREQUENCY;
0148         tx.freq = outofrange_freq[i];
0149 
0150         ret = adjtimex(&tx);
0151         if (ret < 0) {
0152             printf("[FAIL]\n");
0153             printf("Error: adjtimex(ADJ_FREQ, %ld - %ld ppm\n",
0154                 outofrange_freq[i], outofrange_freq[i]>>16);
0155             pass = -1;
0156             goto out;
0157         }
0158         tx.modes = 0;
0159         ret = adjtimex(&tx);
0160         if (tx.freq == outofrange_freq[i]) {
0161             printf("[FAIL]\n");
0162             printf("ERROR: out of range value %ld actually set!\n",
0163                     tx.freq);
0164             pass = -1;
0165             goto out;
0166         }
0167     }
0168 
0169 
0170     if (sizeof(long) == 8) { /* this case only applies to 64bit systems */
0171         for (i = 0; i < NUM_FREQ_INVALID; i++) {
0172             tx.modes = ADJ_FREQUENCY;
0173             tx.freq = invalid_freq[i];
0174             ret = adjtimex(&tx);
0175             if (ret >= 0) {
0176                 printf("[FAIL]\n");
0177                 printf("Error: No failure on invalid ADJ_FREQUENCY %ld\n",
0178                     invalid_freq[i]);
0179                 pass = -1;
0180                 goto out;
0181             }
0182         }
0183     }
0184 
0185     printf("[OK]\n");
0186 out:
0187     /* reset freq to zero */
0188     tx.modes = ADJ_FREQUENCY;
0189     tx.freq = 0;
0190     ret = adjtimex(&tx);
0191 
0192     return pass;
0193 }
0194 
0195 
0196 int set_offset(long long offset, int use_nano)
0197 {
0198     struct timex tmx = {};
0199     int ret;
0200 
0201     tmx.modes = ADJ_SETOFFSET;
0202     if (use_nano) {
0203         tmx.modes |= ADJ_NANO;
0204 
0205         tmx.time.tv_sec = offset / NSEC_PER_SEC;
0206         tmx.time.tv_usec = offset % NSEC_PER_SEC;
0207 
0208         if (offset < 0 && tmx.time.tv_usec) {
0209             tmx.time.tv_sec -= 1;
0210             tmx.time.tv_usec += NSEC_PER_SEC;
0211         }
0212     } else {
0213         tmx.time.tv_sec = offset / USEC_PER_SEC;
0214         tmx.time.tv_usec = offset % USEC_PER_SEC;
0215 
0216         if (offset < 0 && tmx.time.tv_usec) {
0217             tmx.time.tv_sec -= 1;
0218             tmx.time.tv_usec += USEC_PER_SEC;
0219         }
0220     }
0221 
0222     ret = clock_adjtime(CLOCK_REALTIME, &tmx);
0223     if (ret < 0) {
0224         printf("(sec: %ld  usec: %ld) ", tmx.time.tv_sec, tmx.time.tv_usec);
0225         printf("[FAIL]\n");
0226         return -1;
0227     }
0228     return 0;
0229 }
0230 
0231 int set_bad_offset(long sec, long usec, int use_nano)
0232 {
0233     struct timex tmx = {};
0234     int ret;
0235 
0236     tmx.modes = ADJ_SETOFFSET;
0237     if (use_nano)
0238         tmx.modes |= ADJ_NANO;
0239 
0240     tmx.time.tv_sec = sec;
0241     tmx.time.tv_usec = usec;
0242     ret = clock_adjtime(CLOCK_REALTIME, &tmx);
0243     if (ret >= 0) {
0244         printf("Invalid (sec: %ld  usec: %ld) did not fail! ", tmx.time.tv_sec, tmx.time.tv_usec);
0245         printf("[FAIL]\n");
0246         return -1;
0247     }
0248     return 0;
0249 }
0250 
0251 int validate_set_offset(void)
0252 {
0253     printf("Testing ADJ_SETOFFSET... ");
0254     fflush(stdout);
0255 
0256     /* Test valid values */
0257     if (set_offset(NSEC_PER_SEC - 1, 1))
0258         return -1;
0259 
0260     if (set_offset(-NSEC_PER_SEC + 1, 1))
0261         return -1;
0262 
0263     if (set_offset(-NSEC_PER_SEC - 1, 1))
0264         return -1;
0265 
0266     if (set_offset(5 * NSEC_PER_SEC, 1))
0267         return -1;
0268 
0269     if (set_offset(-5 * NSEC_PER_SEC, 1))
0270         return -1;
0271 
0272     if (set_offset(5 * NSEC_PER_SEC + NSEC_PER_SEC / 2, 1))
0273         return -1;
0274 
0275     if (set_offset(-5 * NSEC_PER_SEC - NSEC_PER_SEC / 2, 1))
0276         return -1;
0277 
0278     if (set_offset(USEC_PER_SEC - 1, 0))
0279         return -1;
0280 
0281     if (set_offset(-USEC_PER_SEC + 1, 0))
0282         return -1;
0283 
0284     if (set_offset(-USEC_PER_SEC - 1, 0))
0285         return -1;
0286 
0287     if (set_offset(5 * USEC_PER_SEC, 0))
0288         return -1;
0289 
0290     if (set_offset(-5 * USEC_PER_SEC, 0))
0291         return -1;
0292 
0293     if (set_offset(5 * USEC_PER_SEC + USEC_PER_SEC / 2, 0))
0294         return -1;
0295 
0296     if (set_offset(-5 * USEC_PER_SEC - USEC_PER_SEC / 2, 0))
0297         return -1;
0298 
0299     /* Test invalid values */
0300     if (set_bad_offset(0, -1, 1))
0301         return -1;
0302     if (set_bad_offset(0, -1, 0))
0303         return -1;
0304     if (set_bad_offset(0, 2 * NSEC_PER_SEC, 1))
0305         return -1;
0306     if (set_bad_offset(0, 2 * USEC_PER_SEC, 0))
0307         return -1;
0308     if (set_bad_offset(0, NSEC_PER_SEC, 1))
0309         return -1;
0310     if (set_bad_offset(0, USEC_PER_SEC, 0))
0311         return -1;
0312     if (set_bad_offset(0, -NSEC_PER_SEC, 1))
0313         return -1;
0314     if (set_bad_offset(0, -USEC_PER_SEC, 0))
0315         return -1;
0316 
0317     printf("[OK]\n");
0318     return 0;
0319 }
0320 
0321 int main(int argc, char **argv)
0322 {
0323     if (validate_freq())
0324         return ksft_exit_fail();
0325 
0326     if (validate_set_offset())
0327         return ksft_exit_fail();
0328 
0329     return ksft_exit_pass();
0330 }