radix: Implement radix_tree_destroy()
[akaros.git] / user / utest / sleep.c
1 /* Copyright (c) 2015 Google Inc
2  * Kevin Klues <klueska@google.com>
3  * See LICENSE for details. */
4
5 #include <unistd.h>
6 #include <pthread.h>
7 #include <time.h>
8 #include <ros/time.h>
9 #include <utest/utest.h>
10
11 TEST_SUITE("SLEEP");
12
13 /* Offset in microseconds to account for processing overhead, etc.. */
14 uint64_t offset_usec = 500;
15 /* Number of times to run each test. Take the minimum of the results. */
16 const int NUM_ITERATIONS = 5;
17
18 bool test_nanosleep(void)
19 {
20         const struct timespec times[] = {
21                 {0, 0},
22                 {0, 1},
23                 {0, 999},
24                 {0, 1000},
25                 {0, 1001},
26                 {1, 0},
27                 {1, 1},
28                 {1, 999},
29                 {1, 1000},
30                 {1, 1001},
31                 {2, 123456789},
32         };
33
34         #define check_ntimes(idx, lbound, ubound) \
35         { \
36                 uint64_t tsc, diff_usec = INT_MAX; \
37                 for (int i = 0; i < NUM_ITERATIONS; i++) { \
38                         tsc = read_tsc(); \
39                         nanosleep(&times[idx], NULL); \
40                         diff_usec = MIN(diff_usec, tsc2usec(read_tsc() - tsc)); \
41                 } \
42                 UT_ASSERT_M("Sleep finished too soon", diff_usec >= lbound); \
43                 UT_ASSERT_M("Sleep finished too late", diff_usec <= ubound); \
44         }
45
46         check_ntimes(0, 0, offset_usec + 0);
47         check_ntimes(1, 0, offset_usec + 1);
48         check_ntimes(2, 0, offset_usec + 1);
49         check_ntimes(3, 0, offset_usec + 2);
50         check_ntimes(4, 0, offset_usec + 2);
51         check_ntimes(5, 1000000, offset_usec + 1000000);
52         check_ntimes(6, 1000000, offset_usec + 1000001);
53         check_ntimes(7, 1000000, offset_usec + 1000001);
54         check_ntimes(8, 1000000, offset_usec + 1000002);
55         check_ntimes(9, 1000000, offset_usec + 1000002);
56         check_ntimes(10, 2000000, offset_usec + 2123456);
57
58         /* TODO: Check abort path with 'remaining' parameter. */
59         return true;
60 }
61
62 bool test_usleep(void)
63 {
64         const useconds_t times[] = {
65                 0, 1, 1000, 2000, 1000000, 2000000
66         };
67
68         #define check_utimes(idx, lbound, ubound) \
69         { \
70                 uint64_t tsc, diff_usec = INT_MAX; \
71                 for (int i = 0; i < NUM_ITERATIONS; i++) { \
72                         tsc = read_tsc(); \
73                         usleep(times[idx]); \
74                         diff_usec = MIN(diff_usec, tsc2usec(read_tsc() - tsc)); \
75                 } \
76                 UT_ASSERT_M("Sleep finished too soon", diff_usec >= lbound); \
77                 UT_ASSERT_M("Sleep finished too late", diff_usec <= ubound); \
78         }
79
80         check_utimes(0, 0, offset_usec + 0);
81         check_utimes(1, 1, offset_usec + 1);
82         check_utimes(2, 1000, offset_usec + 1001);
83         check_utimes(3, 2000, offset_usec + 20001);
84         check_utimes(4, 1000000, offset_usec + 1000001);
85         check_utimes(5, 2000000, offset_usec + 2000001);
86         return true;
87 }
88
89 bool test_sleep(void)
90 {
91         const unsigned int times[] = {
92                 0, 1, 2, 3, 4, 5
93         };
94
95         #define check_times(idx, lbound, ubound) \
96         { \
97                 uint64_t tsc, diff_sec = INT_MAX; \
98                 for (int i = 0; i < NUM_ITERATIONS; i++) { \
99                         tsc = read_tsc(); \
100                         sleep(times[idx]); \
101                         diff_sec = MIN(diff_sec, tsc2sec(read_tsc() - tsc)); \
102                 } \
103                 UT_ASSERT_M("Sleep finished too soon", diff_sec >= lbound); \
104                 UT_ASSERT_M("Sleep finished too late", diff_sec <= ubound); \
105         }
106
107         check_times(0, 0, 1);
108         check_times(1, 1, 2);
109         check_times(2, 2, 3);
110         check_times(3, 3, 4);
111         check_times(4, 4, 5);
112         check_times(5, 5, 6);
113         return true;
114 }
115
116 struct utest utests[] = {
117         UTEST_REG(nanosleep),
118         UTEST_REG(usleep),
119         UTEST_REG(sleep),
120 };
121 int num_utests = sizeof(utests) / sizeof(struct utest);
122
123 int main(int argc, char *argv[])
124 {
125         char **whitelist = &argv[1];
126         int whitelist_len = argc - 1;
127
128         RUN_TEST_SUITE(utests, num_utests, whitelist, whitelist_len);
129 }