brintos

brintos / linux-shallow public Read only

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