LCOV - code coverage report
Current view: directory - src/shared/platform - nacl_clock_test.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 89 58 65.2 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : #include <stdio.h>
       8                 : 
       9                 : #include "native_client/src/shared/platform/nacl_clock.h"
      10                 : 
      11                 : #include "native_client/src/shared/platform/platform_init.h"
      12                 : 
      13                 : #include "native_client/src/include/portability.h"
      14                 : #include "native_client/src/shared/platform/nacl_time.h"
      15                 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
      16                 : 
      17                 : /*
      18                 :  * Very basic sanity check.  With clock functionality, tests are a
      19                 :  * pain without a set of globally consistent dependency injection for
      20                 :  * syscalls, since faking out time-related syscalls in the test
      21                 :  * without faking out the same syscalls used by other modules is
      22                 :  * difficult.  Furthermore, this test is trying to verify basic
      23                 :  * functionality -- and testing against a mock interface that works
      24                 :  * according to our expectations of what the syscalls will do isn't
      25                 :  * the same: our assumptions might be wrong, and we ought to have a
      26                 :  * test that verifies end-to-end functionality.  Here, we just compare
      27                 :  * clock_gettime of the realtime clock against gettimeofday, and do
      28                 :  * two monotonic clock samples between a nanosleep to verify that the
      29                 :  * monotonic clock *approximately* measured the sleep duration -- with
      30                 :  * great fuzziness.
      31                 :  *
      32                 :  * On an unloaded i7, 1ms with a 1.25 fuzziness factor and a 100,000
      33                 :  * ns constant syscall overhead works fine.  On bots, we have to be
      34                 :  * much more generous.  (This is especially true for qemu-based
      35                 :  * testing.)
      36                 :  */
      37                 : #define NANOS_PER_MICRO   (1000)
      38                 : #define MICROS_PER_MILLI  (1000)
      39                 : #define NANOS_PER_MILLI   (NANOS_PER_MICRO * MICROS_PER_MILLI)
      40                 : #define MICROS_PER_UNIT   (1000 * 1000)
      41                 : #define NANOS_PER_UNIT    (NANOS_PER_MICRO * MICROS_PER_UNIT)
      42                 : 
      43                 : #define DEFAULT_NANOSLEEP_EXTRA_OVERHEAD  (10 * NANOS_PER_MILLI)
      44                 : #define DEFAULT_NANOSLEEP_EXTRA_FACTOR    (100.0)
      45                 : #define DEFAULT_NANOSLEEP_TIME            (10 * NANOS_PER_MILLI)
      46                 : 
      47                 : /*
      48                 :  * Global testing parameters -- fuzziness coefficients in determining
      49                 :  * what is considered accurate.
      50                 :  */
      51                 : double   g_fuzzy_factor = DEFAULT_NANOSLEEP_EXTRA_FACTOR;
      52                 : uint64_t g_syscall_overhead = DEFAULT_NANOSLEEP_EXTRA_OVERHEAD;
      53                 : uint64_t g_slop_ms = 0;
      54                 : 
      55                 : /*
      56                 :  * ClockMonotonicAccuracyTest samples the NACL_ABI_CLOCK_MONOTONIC
      57                 :  * clock before and after invoking NaClNanosleep and computes the time
      58                 :  * delta.  The test is considered to pass if the time delta is close
      59                 :  * to the requested value.  "Close" is a per-host-OS attribute, thus
      60                 :  * the above testing parameters.
      61                 :  */
      62               1 : int ClockMonotonicAccuracyTest(uint64_t sleep_nanos) {
      63               1 :   int                       num_failures = 0;
      64                 : 
      65                 :   int                       err;
      66                 :   struct nacl_abi_timespec  t_start;
      67                 :   struct nacl_abi_timespec  t_sleep;
      68                 :   struct nacl_abi_timespec  t_end;
      69                 : 
      70                 :   uint64_t                  elapsed_nanos;
      71                 :   uint64_t                  elapsed_lower_bound;
      72                 :   uint64_t                  elapsed_upper_bound;
      73                 : 
      74               1 :   t_sleep.tv_sec  = sleep_nanos / NANOS_PER_UNIT;
      75               1 :   t_sleep.tv_nsec = sleep_nanos % NANOS_PER_UNIT;
      76                 : 
      77               1 :   printf("\nCLOCK_MONOTONIC accuracy test:\n");
      78                 : 
      79               1 :   if (0 != (err = NaClClockGetTime(NACL_ABI_CLOCK_MONOTONIC, &t_start))) {
      80               0 :     fprintf(stderr,
      81                 :             "nacl_clock_test: NaClClockGetTime (start) failed, error %d\n",
      82                 :             err);
      83               0 :     ++num_failures;
      84               0 :     goto done;
      85                 :   }
      86                 :   for (;;) {
      87               1 :     err = NaClNanosleep(&t_sleep, &t_sleep);
      88               1 :     if (0 == err) {
      89               1 :       break;
      90                 :     }
      91               0 :     if (-NACL_ABI_EINTR == err) {
      92                 :       /* interrupted syscall: sleep some more */
      93               0 :       continue;
      94                 :     }
      95               0 :     fprintf(stderr,
      96                 :             "nacl_clock_test: NaClNanoSleep failed, error %d\n", err);
      97               0 :     num_failures++;
      98               0 :     goto done;
      99               0 :   }
     100               1 :   if (0 != (err = NaClClockGetTime(NACL_ABI_CLOCK_MONOTONIC, &t_end))) {
     101               0 :     fprintf(stderr,
     102                 :             "nacl_clock_test: NaClClockGetTime (end) failed, error %d\n",
     103                 :             err);
     104               0 :     return 1;
     105                 :   }
     106                 : 
     107               1 :   elapsed_nanos = (t_end.tv_sec - t_start.tv_sec) * NANOS_PER_UNIT
     108                 :       + (t_end.tv_nsec - t_start.tv_nsec) + g_slop_ms * NANOS_PER_MILLI;
     109                 : 
     110               1 :   elapsed_lower_bound = sleep_nanos;
     111               1 :   elapsed_upper_bound = (uint64_t) (sleep_nanos * g_fuzzy_factor
     112                 :                                     + g_syscall_overhead);
     113                 : 
     114               1 :   printf("requested sleep:      %20"NACL_PRIu64" nS\n", sleep_nanos);
     115               1 :   printf("actual elapsed sleep: %20"NACL_PRIu64" nS\n", elapsed_nanos);
     116               1 :   printf("sleep lower bound:    %20"NACL_PRIu64" nS\n", elapsed_lower_bound);
     117               1 :   printf("sleep upper bound:    %20"NACL_PRIu64" nS\n", elapsed_upper_bound);
     118                 : 
     119               1 :   if (elapsed_nanos < elapsed_lower_bound
     120                 :       || elapsed_upper_bound < elapsed_nanos) {
     121               0 :     printf("discrepancy too large\n");
     122               0 :     num_failures++;
     123                 :   }
     124               1 :  done:
     125               1 :   printf((0 == num_failures) ? "PASSED\n" : "FAILED\n");
     126               1 :   return num_failures;
     127                 : }
     128                 : 
     129                 : /*
     130                 :  * ClockRealtimeAccuracyTest compares the time returned by
     131                 :  * NACL_ABI_CLOCK_REALTIME against that returned by NaClGetTimeOfDay.
     132                 :  */
     133               1 : int ClockRealtimeAccuracyTest(void) {
     134               1 :   int                       num_failures = 0;
     135                 : 
     136                 :   int                       err;
     137                 :   struct nacl_abi_timespec  t_now_ts;
     138                 :   struct nacl_abi_timeval   t_now_tv;
     139                 : 
     140                 :   uint64_t                  t_now_ts_nanos;
     141                 :   uint64_t                  t_now_tv_nanos;
     142                 :   int64_t                   t_now_diff_nanos;
     143                 : 
     144               1 :   printf("\nCLOCK_REALTIME accuracy test:\n");
     145                 : 
     146               1 :   if (0 != (err = NaClClockGetTime(NACL_ABI_CLOCK_REALTIME, &t_now_ts))) {
     147               0 :     fprintf(stderr,
     148                 :             "nacl_clock_test: NaClClockGetTime (now) failed, error %d\n",
     149                 :             err);
     150               0 :     num_failures++;
     151               0 :     goto done;
     152                 :   }
     153               1 :   if (0 != (err = NaClGetTimeOfDay(&t_now_tv))) {
     154               0 :     fprintf(stderr,
     155                 :             "nacl_clock_test: NaClGetTimeOfDay (now) failed, error %d\n",
     156                 :             err);
     157               0 :     num_failures++;
     158               0 :     goto done;
     159                 :   }
     160                 : 
     161               1 :   t_now_ts_nanos = t_now_ts.tv_sec * NANOS_PER_UNIT + t_now_ts.tv_nsec;
     162               1 :   t_now_tv_nanos = t_now_tv.nacl_abi_tv_sec * NANOS_PER_UNIT
     163                 :       + t_now_tv.nacl_abi_tv_usec * NANOS_PER_MICRO;
     164                 : 
     165               1 :   printf("clock_gettime:   %20"NACL_PRIu64" nS\n", t_now_ts_nanos);
     166               1 :   printf("gettimeofday:    %20"NACL_PRIu64" nS\n", t_now_tv_nanos);
     167                 : 
     168               1 :   t_now_diff_nanos = t_now_ts_nanos - t_now_tv_nanos;
     169               1 :   if (t_now_diff_nanos < 0) {
     170               0 :     t_now_diff_nanos = -t_now_diff_nanos;
     171                 :   }
     172               1 :   printf("time difference: %20"NACL_PRId64" nS\n", t_now_diff_nanos);
     173                 : 
     174               1 :   if (t_now_ts_nanos < g_syscall_overhead) {
     175               0 :     printf("discrepancy too large\n");
     176               0 :     num_failures++;
     177                 :   }
     178               1 :  done:
     179               1 :   printf((0 == num_failures) ? "PASSED\n" : "FAILED\n");
     180               1 :   return num_failures;
     181                 : }
     182                 : 
     183               1 : int main(int ac, char **av) {
     184               1 :   uint64_t                  sleep_nanos = DEFAULT_NANOSLEEP_TIME;
     185                 : 
     186                 :   int                       opt;
     187               1 :   uint32_t                  num_failures = 0;
     188                 : 
     189               1 :   puts("This is a basic functionality test being repurposed as an");
     190               1 :   puts(" unit/regression test.  The test parameters default to values that");
     191               1 :   puts("are more appropriate for heavily loaded continuous-testing robots.");
     192               1 :   printf("\nThe default values are:\n -S %"NACL_PRIu64
     193                 :          " -f %f -o %"NACL_PRIu64" -s %"NACL_PRIu64"\n\n",
     194                 :          sleep_nanos, g_fuzzy_factor, g_syscall_overhead, g_slop_ms);
     195               1 :   puts("For testing functionality, this test should be run with a different");
     196               1 :   puts("set of parameters.  On an unloaded i7, a sleep duration (-S) of");
     197               1 :   puts("1000000 ns (one millisecond), with a fuzziness factor (-f) of 1.25,");
     198               1 :   puts("a constant test overhead of 100000 ns (100 us), and a");
     199               1 :   puts("sleep duration \"slop\" (-s) of 0 is fine.");
     200                 : 
     201               1 :   while (-1 != (opt = getopt(ac, av, "f:o:s:S:"))) {
     202               1 :     switch (opt) {
     203                 :       case 'f':
     204               0 :         g_fuzzy_factor = strtod(optarg, (char **) NULL);
     205               0 :         break;
     206                 :       case 'o':
     207               0 :         g_syscall_overhead = strtoul(optarg, (char **) NULL, 0);
     208               0 :         break;
     209                 :       case 's':
     210               1 :         g_slop_ms = strtoul(optarg, (char **) NULL, 0);
     211               1 :         break;
     212                 :       case 'S':
     213               0 :         sleep_nanos = strtoul(optarg, (char **) NULL, 0);
     214               0 :         break;
     215                 :       default:
     216               0 :         fprintf(stderr, "nacl_clock_test: unrecognized option `%c'.\n",
     217                 :                 opt);
     218               0 :         fprintf(stderr,
     219                 :                 "Usage: nacl_clock_test [-f fuzz_factor] [-s sleep_nanos]\n"
     220                 :                 "       [-o syscall_overhead_nanos]\n");
     221               0 :         return -1;
     222                 :     }
     223                 :   }
     224                 : 
     225               1 :   NaClPlatformInit();
     226                 : 
     227               1 :   num_failures += ClockMonotonicAccuracyTest(sleep_nanos);
     228               1 :   num_failures += ClockRealtimeAccuracyTest();
     229                 : 
     230               1 :   NaClPlatformFini();
     231                 : 
     232               1 :   return num_failures;
     233                 : }

Generated by: LCOV version 1.7