libamxc  1.10.3
C Generic Data Containers
test_amxc_timestamp.c File Reference
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <setjmp.h>
#include <stdarg.h>
#include <cmocka.h>
#include <amxc/amxc_timestamp.h>
#include "test_amxc_timestamp.h"
#include <amxc/amxc_macros.h>

Go to the source code of this file.

Macros

#define _GNU_SOURCE
 

Functions

void test_amxc_ts_now (UNUSED void **state)
 
void test_amxc_ts_parse_valid (UNUSED void **state)
 
void test_amxc_ts_parse_invalid (UNUSED void **state)
 
void test_amxc_ts_format_valid (UNUSED void **state)
 
void test_amxc_ts_format_invalid (UNUSED void **state)
 
void test_amxc_ts_format_precision_valid (UNUSED void **state)
 
void test_amxc_ts_is_valid (UNUSED void **state)
 
void test_amxc_ts_compare (UNUSED void **state)
 
void test_amxc_ts_to_tm (UNUSED void **state)
 
void test_amxc_ts_to_local (UNUSED void **state)
 
void test_amxc_ts_from_tm (UNUSED void **state)
 

Macro Definition Documentation

◆ _GNU_SOURCE

#define _GNU_SOURCE

Definition at line 55 of file test_amxc_timestamp.c.

Function Documentation

◆ test_amxc_ts_compare()

void test_amxc_ts_compare ( UNUSED void **  state)

Definition at line 274 of file test_amxc_timestamp.c.

274  {
275  amxc_ts_t ts_a;
276  amxc_ts_t ts_b;
277 
278  assert_int_equal(amxc_ts_parse(&ts_a, "1970-07-28T15:45:00Z", strlen("1970-07-28T15:45:00Z")), 0);
279  assert_int_equal(amxc_ts_parse(&ts_b, "1970-08-28T15:45:00Z", strlen("1970-08-28T15:45:00Z")), 0);
280 
281  assert_true(amxc_ts_compare(&ts_a, &ts_b) < 0);
282  assert_true(amxc_ts_compare(&ts_b, &ts_a) > 0);
283  assert_true(amxc_ts_compare(&ts_a, &ts_a) == 0);
284 
285  assert_int_equal(amxc_ts_parse(&ts_a, "1970-07-28T15:45:00.123Z", strlen("1970-07-28T15:45:00Z.123")), 0);
286  assert_int_equal(amxc_ts_parse(&ts_b, "1970-07-28T15:45:00.456Z", strlen("1970-07-28T15:45:00Z.456")), 0);
287 
288  assert_true(amxc_ts_compare(&ts_a, &ts_b) < 0);
289  assert_true(amxc_ts_compare(&ts_b, &ts_a) > 0);
290  assert_true(amxc_ts_compare(&ts_a, &ts_a) == 0);
291 
292  assert_true(amxc_ts_compare(NULL, &ts_a) == 0);
293  assert_true(amxc_ts_compare(&ts_a, NULL) == 0);
294 }
int amxc_ts_compare(const amxc_ts_t *tsp1, const amxc_ts_t *tsp2)
Checks if tsp1 comes after tsp2.
int amxc_ts_parse(amxc_ts_t *tsp, const char *str, size_t len)
Transforms the given string in to unix epoch time.
The timestamp structure (unix epoch time).

◆ test_amxc_ts_format_invalid()

void test_amxc_ts_format_invalid ( UNUSED void **  state)

Definition at line 195 of file test_amxc_timestamp.c.

195  {
196  amxc_ts_t ts;
197  char str_ts[40];
198 
199  assert_int_equal(amxc_ts_parse(&ts, "1970-07-28T15:45:00Z", strlen("1970-07-28T15:45:00Z")), 0);
200 
201  assert_int_equal(amxc_ts_format(&ts, NULL, 0), 0);
202  assert_int_equal(amxc_ts_format(&ts, str_ts, 0), 0);
203  assert_int_equal(amxc_ts_format(&ts, str_ts, 19), 0);
204  assert_int_equal(amxc_ts_format(NULL, str_ts, 40), 0);
205 
206  assert_int_equal(amxc_ts_format_precision(&ts, str_ts, 40, -1), 0);
207  assert_int_equal(amxc_ts_format_precision(&ts, str_ts, 40, 10), 0);
208 
209  assert_int_equal(amxc_ts_format_precision(&ts, NULL, 0, 3), 0);
210  assert_int_equal(amxc_ts_format_precision(&ts, str_ts, 0, 6), 0);
211  assert_int_equal(amxc_ts_format_precision(&ts, str_ts, 19, 9), 0);
212  assert_int_equal(amxc_ts_format_precision(NULL, str_ts, 40, 2), 0);
213 
214 }
size_t amxc_ts_format(const amxc_ts_t *tsp, char *dst, size_t len)
Transforms unix epoch time to a string.
size_t amxc_ts_format_precision(const amxc_ts_t *tsp, char *dst, size_t len, int precision)
Transforms unix epoch time to a string.

◆ test_amxc_ts_format_precision_valid()

void test_amxc_ts_format_precision_valid ( UNUSED void **  state)

Definition at line 216 of file test_amxc_timestamp.c.

216  {
217  amxc_ts_t ts;
218  char str_ts[40];
219  const char* formats[] = {
220  "1970-07-28T15:45:00Z",
221  "0001-01-01T00:00:00Z",
222  "2020-02-29T16:16:16+02:00",
223  "2020-02-29T16:16:16-01:15",
224  "2000-02-28T23:14:00Z",
225  "1970-01-01T00:00:00Z",
226  "2017-11-11T11:11:11.123+02:00",
227  "2017-11-11T11:11:11.123456Z",
228  "1994-10-01T00:00:00.123456789-02:30",
229  NULL
230  };
231 
232  for(int i = 0; formats[i] != NULL; i++) {
233  assert_int_equal(amxc_ts_parse(&ts, formats[i], strlen(formats[i])), 0);
234  assert_int_not_equal(amxc_ts_format_precision(&ts, str_ts, 40, 3), 0);
235  assert_int_not_equal(amxc_ts_format_precision(&ts, str_ts, 40, 4), 0);
236  assert_int_not_equal(amxc_ts_format_precision(&ts, str_ts, 40, 6), 0);
237  assert_int_not_equal(amxc_ts_format_precision(&ts, str_ts, 40, 8), 0);
238  assert_int_not_equal(amxc_ts_format_precision(&ts, str_ts, 40, 9), 0);
239  }
240 }

◆ test_amxc_ts_format_valid()

void test_amxc_ts_format_valid ( UNUSED void **  state)

Definition at line 171 of file test_amxc_timestamp.c.

171  {
172  amxc_ts_t ts;
173  char str_ts[40];
174  const char* formats[] = {
175  "1970-07-28T15:45:00Z",
176  "0001-01-01T00:00:00Z",
177  "2020-02-29T16:16:16+02:00",
178  "2020-02-29T16:16:16-01:15",
179  "2000-02-28T23:14:00Z",
180  "1970-01-01T00:00:00Z",
181  "2017-11-11T11:11:11.123+02:00",
182  "2017-11-11T11:11:11.123456Z",
183  "1994-10-01T00:00:00.123456789-02:30",
184  NULL
185  };
186 
187  for(int i = 0; formats[i] != NULL; i++) {
188  printf("Checking [%s]\n", formats[i]);
189  assert_int_equal(amxc_ts_parse(&ts, formats[i], strlen(formats[i])), 0);
190  assert_int_equal(amxc_ts_format(&ts, str_ts, 40), strlen(formats[i]));
191  assert_string_equal(str_ts, formats[i]);
192  }
193 }

◆ test_amxc_ts_from_tm()

void test_amxc_ts_from_tm ( UNUSED void **  state)

Definition at line 357 of file test_amxc_timestamp.c.

357  {
358  amxc_ts_t ts;
359  time_t rawtime;
360  struct tm* timeinfo = NULL; // get date and time info
361 
362  time(&rawtime);
363  timeinfo = localtime(&rawtime);
364 
365  assert_int_equal(amxc_ts_from_tm(&ts, timeinfo), 0);
366  assert_int_equal(rawtime, ts.sec);
367 }
int amxc_ts_from_tm(amxc_ts_t *const tsp, struct tm *tmp)
Converts a broken down time in a struct tm to a timestamp structure.

◆ test_amxc_ts_is_valid()

void test_amxc_ts_is_valid ( UNUSED void **  state)

Definition at line 242 of file test_amxc_timestamp.c.

242  {
243  char str_ts[40];
244 
245  amxc_ts_t ts;
246  ts.nsec = 0;
247  ts.sec = 0;
248  ts.offset = 0;
249 
250  assert_true(amxc_ts_is_valid(&ts));
251 
252  ts.sec = INT64_C(-62135596800) - 1;
253  assert_false(amxc_ts_is_valid(&ts));
254  ts.sec = INT64_C(253402300799) + 1;
255  assert_false(amxc_ts_is_valid(&ts));
256 
257  ts.sec = 0;
258  ts.nsec = -1;
259  assert_false(amxc_ts_is_valid(&ts));
260  ts.nsec = 1999999999;
261  assert_false(amxc_ts_is_valid(&ts));
262  assert_int_equal(amxc_ts_format(&ts, str_ts, 40), 0);
263  assert_int_equal(amxc_ts_format_precision(&ts, str_ts, 40, 3), 0);
264 
265  ts.nsec = 0;
266  ts.offset = -1440;
267  assert_false(amxc_ts_is_valid(&ts));
268  ts.offset = 1440;
269  assert_false(amxc_ts_is_valid(&ts));
270 
271  assert_false(amxc_ts_is_valid(NULL));
272 }
bool amxc_ts_is_valid(const amxc_ts_t *tsp)
Checks if a timestamp is valid.
int32_t nsec
int16_t offset

◆ test_amxc_ts_now()

void test_amxc_ts_now ( UNUSED void **  state)

Definition at line 68 of file test_amxc_timestamp.c.

68  {
69  amxc_ts_t ts1, ts2;
70 
71  assert_int_equal(amxc_ts_now(&ts1), 0);
72  assert_int_not_equal(ts1.sec, 0);
73  assert_int_not_equal(amxc_ts_now(NULL), 0);
74 
75  struct timespec waittime = {0, 300 * 1000 * 1000L};
76  while(nanosleep(&waittime, NULL) != 0) {
77  }
78  assert_int_equal(amxc_ts_now(&ts2), 0);
79  assert_true(amxc_ts_compare(&ts2, &ts1) > 0);
80 
81  // The POSIX standard guarantees that at least 300 000 000 nanoseconds
82  // have passed between the calls, so the diff should exceed that
83  int64_t diff_us = ts2.nsec - ts1.nsec;
84  int64_t diff = (ts2.sec - ts1.sec) * 1000 * 1000 * 1000L + diff_us;
85  assert_true(diff > 300 * 1000 * 1000L);
86 }
int amxc_ts_now(amxc_ts_t *tsp)
Takes current time as unix epoch time.

◆ test_amxc_ts_parse_invalid()

void test_amxc_ts_parse_invalid ( UNUSED void **  state)

Definition at line 125 of file test_amxc_timestamp.c.

125  {
126  amxc_ts_t ts;
127  const char* formats[] = {
128  "1970-14-28T15:45:00Z",
129  "0001-01-32T00:00:00Z",
130  "2020-02-30T16:16:16+02:00",
131  "2000-02-31T16:16:16+02:00",
132  "0000-02-29T16:16:16.123+02:00",
133  "2019-02-29T16:16:16.123+02:00",
134  "1984-04-31T00:00:00Z",
135  "1984-04-30T26:00:00Z",
136  "1984-04-30T13:70:00Z",
137  "1984-04-30T13:10:70Z",
138  "1984-04-30T13:12:11.9999999999Z",
139  "1984-04-30T13:12:11.999999999+24:00",
140  "1984-0A-30T13:10:70Z",
141  "1984-A0-30T12:10:70Z",
142  "Q984-01-30T12:10:70Z",
143  "1Q84-01-30T12:10:70Z",
144  "19Q4-01-30T12:10:70Z",
145  "198Q-01-30T12:10:70Z",
146  "184-01-30T10:10:10.9999999-11:00",
147  "1984-01-30Z10:10:20.9999999-11:00",
148  "1984-01-30T10:10:30Q-11:00",
149  "2000.02-28T23:14:00Z",
150  "2000-02/28T23:14:00Z",
151  "2000-02-28T23.14:00Z",
152  "2000-02-28T23:14-00Z",
153  "2000-02-28T23:14:00,123Z",
154  "2000-00-28T23:14:00.123Z",
155  "2000-01-01T24:00:00.000Z",
156  "2000-01-01T23:60:00.000Z",
157  "2000-01-01T23:00:60.000Z",
158  NULL
159  };
160 
161  for(int i = 0; formats[i] != NULL; i++) {
162  printf("Checking [%s]\n", formats[i]);
163  assert_int_not_equal(amxc_ts_parse(&ts, formats[i], strlen(formats[i])), 0);
164  }
165 
166  assert_int_not_equal(amxc_ts_parse(NULL, formats[0], strlen(formats[0])), 0);
167  assert_int_not_equal(amxc_ts_parse(&ts, NULL, strlen(formats[0])), 0);
168  assert_int_not_equal(amxc_ts_parse(&ts, formats[0], 10), 0);
169 }

◆ test_amxc_ts_parse_valid()

void test_amxc_ts_parse_valid ( UNUSED void **  state)

Definition at line 88 of file test_amxc_timestamp.c.

88  {
89  amxc_ts_t ts;
90  const char* formats[] = {
91  "1970-07-28T15:45:00Z",
92  "0001-01-01T00:00:00Z",
93  "2020-02-29T16:16:16+02:00",
94  "2020-02-29T16:16:16.123+02:00",
95  "2020-02-29T16:16:16-01:15",
96  "2020-02-29T16:16:16.123456-01:15",
97  "2000-02-28T23:14:00Z",
98  "1970-01-01T00:00:00Z",
99  "1970-01-01t00:00:00Z",
100  "1970-01-01 00:00:00Z",
101  "1970-01-01T00:00:00z",
102  NULL
103  };
104 
105  const int64_t timestamps[] = {
106  18027900,
107  -62135596800,
108  1582985776,
109  1582985776,
110  1582997476,
111  1582997476,
112  951779640,
113  0,
114  0,
115  0,
116  0,
117  };
118 
119  for(int i = 0; formats[i] != NULL; i++) {
120  assert_int_equal(amxc_ts_parse(&ts, formats[i], strlen(formats[i])), 0);
121  assert_int_equal(ts.sec, timestamps[i]);
122  }
123 }

◆ test_amxc_ts_to_local()

void test_amxc_ts_to_local ( UNUSED void **  state)

Definition at line 324 of file test_amxc_timestamp.c.

324  {
325  amxc_ts_t ts;
326  char* current_tz = getenv("TZ");
327  char str_ts[40];
328  time_t rawtime;
329  struct tm* timeinfo; // get date and time info
330 
331  time(&rawtime);
332  timeinfo = localtime(&rawtime);
333 
334  setenv("TZ", "Europe/Brussels", true);
335  assert_int_equal(amxc_ts_parse(&ts, "2020-06-17T15:35:22Z", strlen("2020-06-17T15:35:22Z")), 0);
336  assert_int_equal(ts.offset, 0);
337  assert_int_equal(amxc_ts_to_local(&ts), 0);
338  if(timeinfo->tm_isdst == 0) {
339  assert_int_equal(ts.offset, 60);
340  assert_int_equal(amxc_ts_format(&ts, str_ts, 40), strlen("2020-06-17T16:35:22+01:00"));
341  assert_string_equal(str_ts, "2020-06-17T16:35:22+01:00");
342  } else {
343  assert_int_equal(ts.offset, 120);
344  assert_int_equal(amxc_ts_format(&ts, str_ts, 40), strlen("2020-06-17T17:35:22+02:00"));
345  assert_string_equal(str_ts, "2020-06-17T17:35:22+02:00");
346  }
347 
348  assert_int_not_equal(amxc_ts_to_local(NULL), 0);
349 
350  if(current_tz != NULL) {
351  setenv("TZ", current_tz, true);
352  } else {
353  unsetenv("TZ");
354  }
355 }
int amxc_ts_to_local(amxc_ts_t *tsp)
Adds the local time offset to the timestamp structure.

◆ test_amxc_ts_to_tm()

void test_amxc_ts_to_tm ( UNUSED void **  state)

Definition at line 296 of file test_amxc_timestamp.c.

296  {
297  amxc_ts_t ts;
298  struct tm tm;
299 
300  assert_int_equal(amxc_ts_parse(&ts, "2020-06-17T15:35:22+02:00", strlen("2020-06-17T15:35:22+02:00")), 0);
301  assert_int_equal(amxc_ts_to_tm_utc(&ts, &tm), 0);
302  assert_int_equal(tm.tm_hour, 13);
303  assert_int_equal(tm.tm_min, 35);
304  assert_int_equal(tm.tm_sec, 22);
305  assert_int_equal(tm.tm_mday, 17);
306  assert_int_equal(tm.tm_mon, 5);
307  assert_int_equal(tm.tm_year, 120);
308 
309  assert_int_equal(amxc_ts_to_tm_local(&ts, &tm), 0);
310  assert_int_equal(tm.tm_hour, 15);
311  assert_int_equal(tm.tm_min, 35);
312  assert_int_equal(tm.tm_sec, 22);
313  assert_int_equal(tm.tm_mday, 17);
314  assert_int_equal(tm.tm_mon, 5);
315  assert_int_equal(tm.tm_year, 120);
316 
317  assert_int_not_equal(amxc_ts_to_tm_utc(NULL, &tm), 0);
318  assert_int_not_equal(amxc_ts_to_tm_utc(&ts, NULL), 0);
319 
320  ts.offset = 1440;
321  assert_int_not_equal(amxc_ts_to_tm_utc(&ts, &tm), 0);
322 }
int amxc_ts_to_tm_utc(const amxc_ts_t *tsp, struct tm *tmp)
Converts timestamp in unix epoch time to a struct tm type in UTC time.
int amxc_ts_to_tm_local(const amxc_ts_t *tsp, struct tm *tmp)
Converts timestamp in unix epoch time to a struct tm type in local time.