fix malloc-brk-fail
[libc-test] / src / functional / strptime.c
1 // SPDX-License-Identifier: MIT
2
3 #define _GNU_SOURCE     /* For tm_gmtoff */
4 #include <stddef.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <time.h>
8 #include "test.h"
9
10 /**
11  * checkStrptime - parse time and check if it matches expected value
12  *
13  * This function compares time and date fields of tm structure only.
14  * It's because tm_wday and tm_yday may - but don't have to - be set
15  * while parsing a date.
16  */
17 static void checkStrptime(const char *s, const char *format, const struct tm *expected) {
18         struct tm tm = { };
19         const char *ret;
20
21         ret = strptime(s, format, &tm);
22         if (!ret || *ret != '\0') {
23                 t_error("\"%s\": failed to parse \"%s\"\n", format, s);
24         } else if (tm.tm_sec != expected->tm_sec ||
25                    tm.tm_min != expected->tm_min ||
26                    tm.tm_hour != expected->tm_hour ||
27                    tm.tm_mday != expected->tm_mday ||
28                    tm.tm_mon != expected->tm_mon ||
29                    tm.tm_year != expected->tm_year) {
30                 char buf1[64];
31                 char buf2[64];
32
33                 strftime(buf1, sizeof(buf1), "%FT%H:%M:%S%Z", expected);
34                 strftime(buf2, sizeof(buf2), "%FT%H:%M:%S%Z", &tm);
35
36                 t_error("\"%s\": for \"%s\" expected %s but got %s\n", format, s, buf1, buf2);
37         }
38 }
39
40 static void checkStrptimeTz(const char *s, int h, int m) {
41         long int expected = h * 3600 + m * 60;
42         struct tm tm = { };
43         const char *ret;
44
45         ret = strptime(s, "%z", &tm);
46         if (!ret || *ret != '\0') {
47                 t_error("\"%%z\": failed to parse \"%s\"\n", s);
48         } else if (tm.tm_gmtoff != expected) {
49                 t_error("\"%%z\": for \"%s\" expected tm_gmtoff %ld but got %ld\n", s, tm.tm_gmtoff, expected);
50         }
51 }
52
53 static struct tm tm1 = {
54         .tm_sec = 8,
55         .tm_min = 57,
56         .tm_hour = 20,
57         .tm_mday = 0,
58         .tm_mon = 0,
59         .tm_year = 0,
60 };
61
62 static struct tm tm2 = {
63         .tm_sec = 0,
64         .tm_min = 0,
65         .tm_hour = 0,
66         .tm_mday = 25,
67         .tm_mon = 8 - 1,
68         .tm_year = 1991 - 1900,
69 };
70
71 static struct tm tm3 = {
72         .tm_sec = 0,
73         .tm_min = 0,
74         .tm_hour = 0,
75         .tm_mday = 21,
76         .tm_mon = 10 - 1,
77         .tm_year = 2015 - 1900,
78 };
79
80 static struct tm tm4 = {
81         .tm_sec = 0,
82         .tm_min = 0,
83         .tm_hour = 0,
84         .tm_mday = 10,
85         .tm_mon = 7 - 1,
86         .tm_year = 1856 - 1900,
87 };
88
89 int main() {
90         setenv("TZ", "UTC0", 1);
91
92         /* Time */
93         checkStrptime("20:57:08", "%H:%M:%S", &tm1);
94         checkStrptime("20:57:8", "%R:%S", &tm1);
95         checkStrptime("20:57:08", "%T", &tm1);
96
97         /* Format */
98         checkStrptime("20:57:08", "%H : %M  :  %S", &tm1);
99         checkStrptime("20 57  08", "%H %M %S", &tm1);
100         checkStrptime("20%57%08", "%H %% %M%%%S", &tm1);
101         checkStrptime("foo20bar57qux08      ", "foo %Hbar %M qux%S ", &tm1);
102
103         /* Date */
104         checkStrptime("1991-08-25", "%Y-%m-%d", &tm2);
105         checkStrptime("25.08.91", "%d.%m.%y", &tm2);
106         checkStrptime("08/25/91", "%D", &tm2);
107         checkStrptime("21.10.15", "%d.%m.%y", &tm3);
108         checkStrptime("10.7.56 in 18th", "%d.%m.%y in %C th", &tm4);
109
110         /* Glibc */
111         checkStrptime("1856-07-10", "%F", &tm4);
112         checkStrptime("683078400", "%s", &tm2);
113         checkStrptimeTz("+0200", 2, 0);
114         checkStrptimeTz("-0530", -5, -30);
115         checkStrptimeTz("-06", -6, 0);
116
117         return t_status;
118 }