]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
test: add tests for system adjtime() and ntp_adjtime()
authorMiroslav Lichvar <mlichvar@redhat.com>
Thu, 10 Sep 2015 13:34:56 +0000 (15:34 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 17 Sep 2015 08:56:51 +0000 (10:56 +0200)
Include a test program to determine how the adjtime() implementation
behaves. Check the range of supported offset, support for readonly
operation, and slew rate with different update intervals and offsets.

Also, add a test for ntp_adjtime() to check what frequency range it
supports.

test/kernel/Makefile [new file with mode: 0644]
test/kernel/adjtime.c [new file with mode: 0644]
test/kernel/ntpadjtime.c [new file with mode: 0644]

diff --git a/test/kernel/Makefile b/test/kernel/Makefile
new file mode 100644 (file)
index 0000000..6ec8341
--- /dev/null
@@ -0,0 +1,7 @@
+CFLAGS=-O2 -Wall
+PROGS=adjtime ntpadjtime
+
+all: $(PROGS)
+
+clean:
+       rm -f $(PROGS)
diff --git a/test/kernel/adjtime.c b/test/kernel/adjtime.c
new file mode 100644 (file)
index 0000000..0ca8ff2
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) Miroslav Lichvar  2015
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/* Test the system adjtime() function. Check the range of supported offset,
+   support for readonly operation, and slew rate with different update
+   intervals and offsets. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+static int
+diff_tv(struct timeval *tv1, struct timeval *tv2)
+{
+  return 1000000 * (tv1->tv_sec - tv2->tv_sec) + (tv1->tv_usec - tv2->tv_usec);
+}
+
+static struct timeval
+usec_to_tv(int usec)
+{
+  struct timeval tv;
+
+  tv.tv_sec = usec / 1000000;
+  tv.tv_usec = usec % 1000000;
+
+  return tv;
+}
+
+static int
+try_adjtime(struct timeval *new, struct timeval *old)
+{
+  int r;
+
+  r = adjtime(new, old);
+  if (r)
+    printf("adjtime() failed : %s ", strerror(errno));
+  return r;
+}
+
+static void
+reset_adjtime(void)
+{
+  struct timeval tv;
+
+  tv = usec_to_tv(0);
+  try_adjtime(&tv, NULL);
+}
+
+static void
+test_range(void)
+{
+  struct timeval tv;
+  int i;
+
+  printf("range:\n");
+
+  for (i = 0; i < sizeof (time_t) * 8; i++) {
+    tv.tv_usec = 0;
+    tv.tv_sec = (1ULL << i) - 1;
+    printf("%20lld s : ", (long long)tv.tv_sec);
+    printf("%s\n", !try_adjtime(&tv, NULL) ? "ok" : "");
+    tv.tv_sec = ~tv.tv_sec;
+    printf("%20lld s : ", (long long)tv.tv_sec);
+    printf("%s\n", !try_adjtime(&tv, NULL) ? "ok" : "");
+  }
+}
+
+static void
+test_readonly(void)
+{
+  struct timeval tv1, tv2;
+  int i, r;
+
+  printf("readonly:\n");
+
+  for (i = 0; i <= 20; i++) {
+    tv1 = usec_to_tv(1 << i);
+
+    printf("%9d us : ", 1 << i);
+    try_adjtime(&tv1, NULL);
+    r = !try_adjtime(NULL, &tv2) && !diff_tv(&tv1, &tv2);
+    printf("%s\n", r ? "ok" : "fail");
+  }
+}
+
+static void
+test_readwrite(void)
+{
+  struct timeval tv1, tv2, tv3;
+  int i, r;
+
+  printf("readwrite:\n");
+
+  for (i = 0; i <= 20; i++) {
+    tv1 = usec_to_tv(1 << i);
+    tv3 = usec_to_tv(0);
+
+    printf("%9d us : ", 1 << i);
+    try_adjtime(&tv1, NULL);
+    r = !try_adjtime(&tv3, &tv2) && !diff_tv(&tv1, &tv2);
+    printf("%s\n", r ? "ok" : "fail");
+  }
+}
+
+static void
+xusleep(int usec)
+{
+  struct timeval tv;
+
+  tv = usec_to_tv(usec);
+  select(0, NULL, NULL, NULL, &tv);
+}
+
+static void
+test_slew(void)
+{
+  struct timeval tv1, tv2, tv3;
+  int i, j, k, diff, min, has_min;
+
+  printf("slew:\n");
+
+  for (i = 9; i <= 20; i++) {
+    printf("%9d us : ", 1 << i);
+    for (j = 4; j <= 20; j += 4) {
+      for (min = has_min = 0, k = 4; k < 16; k += 2) {
+
+        tv1 = usec_to_tv(1 << j);
+        tv3 = usec_to_tv(0);
+
+        xusleep(1 << i);
+        reset_adjtime();
+
+        xusleep(1 << i);
+        if (try_adjtime(&tv1, NULL))
+          continue;
+
+        xusleep(1 << i);
+        if (try_adjtime(&tv3, &tv2))
+          continue;
+
+        diff = diff_tv(&tv1, &tv2);
+        if (!has_min || min > diff) {
+          min = diff;
+          has_min = 1;
+        }
+      }
+
+      if (!has_min)
+        continue;
+
+      printf(" %5d (%d)", min, 1 << j);
+      fflush(stdout);
+    }
+    printf("\n");
+  }
+}
+
+int
+main()
+{
+  test_range();
+  test_readonly();
+  test_readwrite();
+  test_slew();
+
+  reset_adjtime();
+
+  return 0;
+}
diff --git a/test/kernel/ntpadjtime.c b/test/kernel/ntpadjtime.c
new file mode 100644 (file)
index 0000000..d6be154
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) Miroslav Lichvar  2015
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+/* Check the frequency range of the system ntp_adjtime() implementation */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+
+static int
+try_ntpadjtime(struct timex *t)
+{
+  int r;
+  r = ntp_adjtime(t);
+  if (r < 0)
+    printf("ntp_adjtime() failed : %s ", strerror(errno));
+  return r;
+}
+
+static void
+reset_ntpadjtime(void)
+{
+  struct timex t;
+
+  t.modes = MOD_OFFSET | MOD_FREQUENCY;
+  t.offset = 0;
+  t.freq = 0;
+  try_ntpadjtime(&t);
+}
+
+static void
+test_freqrange(void)
+{
+  struct timex t;
+  int i;
+
+  printf("freq range:\n");
+
+  for (i = 0; i <= 1000; i += 50) {
+    t.modes = MOD_FREQUENCY;
+    t.freq = i << 16;
+    printf("%4d ppm => ", i);
+    if (try_ntpadjtime(&t) < 0)
+      continue;
+
+    printf("%4ld ppm : ", t.freq / (1 << 16));
+    printf("%s\n", t.freq == i << 16 ? "ok" : "fail");
+  }
+}
+
+int
+main()
+{
+  test_freqrange();
+
+  reset_ntpadjtime();
+
+  return 0;
+}