1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <string.h> |
4 | #include <time.h> |
5 | |
6 | |
7 | static int |
8 | do_bz18985 (void) |
9 | { |
10 | char buf[1000]; |
11 | struct tm ttm; |
12 | int rc, ret = 0; |
13 | |
14 | memset (&ttm, 1, sizeof (ttm)); |
15 | ttm.tm_zone = NULL; /* Dereferenced directly if non-NULL. */ |
16 | rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z" , &ttm); |
17 | |
18 | if (rc == 66) |
19 | { |
20 | const char expected[] |
21 | = "? ? ? ? ? ? 16843009 16843009:16843009:16843009 16844909 +467836 ?" ; |
22 | if (0 != strcmp (buf, expected)) |
23 | { |
24 | printf (format: "expected:\n %s\ngot:\n %s\n" , expected, buf); |
25 | ret += 1; |
26 | } |
27 | } |
28 | else |
29 | { |
30 | printf (format: "expected 66, got %d\n" , rc); |
31 | ret += 1; |
32 | } |
33 | |
34 | /* Check negative values as well. */ |
35 | memset (&ttm, 0xFF, sizeof (ttm)); |
36 | ttm.tm_zone = NULL; /* Dereferenced directly if non-NULL. */ |
37 | rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z" , &ttm); |
38 | |
39 | if (rc == 30) |
40 | { |
41 | const char expected[] = "? ? ? ? ? ? -1 -1:-1:-1 1899 " ; |
42 | if (0 != strcmp (buf, expected)) |
43 | { |
44 | printf (format: "expected:\n %s\ngot:\n %s\n" , expected, buf); |
45 | ret += 1; |
46 | } |
47 | } |
48 | else |
49 | { |
50 | printf (format: "expected 30, got %d\n" , rc); |
51 | ret += 1; |
52 | } |
53 | |
54 | return ret; |
55 | } |
56 | |
57 | static struct |
58 | { |
59 | const char *fmt; |
60 | size_t min; |
61 | size_t max; |
62 | } tests[] = |
63 | { |
64 | { "%2000Y" , 2000, 4000 }, |
65 | { "%02000Y" , 2000, 4000 }, |
66 | { "%_2000Y" , 2000, 4000 }, |
67 | { "%-2000Y" , 2000, 4000 }, |
68 | }; |
69 | #define ntests (sizeof (tests) / sizeof (tests[0])) |
70 | |
71 | |
72 | static int |
73 | do_test (void) |
74 | { |
75 | size_t cnt; |
76 | int result = 0; |
77 | |
78 | time_t tnow = time (NULL); |
79 | struct tm *now = localtime (&tnow); |
80 | |
81 | for (cnt = 0; cnt < ntests; ++cnt) |
82 | { |
83 | size_t size = 0; |
84 | int res; |
85 | char *buf = NULL; |
86 | |
87 | do |
88 | { |
89 | size += 500; |
90 | buf = (char *) realloc (ptr: buf, size: size); |
91 | if (buf == NULL) |
92 | { |
93 | puts (s: "out of memory" ); |
94 | exit (1); |
95 | } |
96 | |
97 | res = strftime (buf, size, tests[cnt].fmt, now); |
98 | if (res != 0) |
99 | break; |
100 | } |
101 | while (size < tests[cnt].max); |
102 | |
103 | if (res == 0) |
104 | { |
105 | printf (format: "%zu: %s: res == 0 despite size == %zu\n" , |
106 | cnt, tests[cnt].fmt, size); |
107 | result = 1; |
108 | } |
109 | else if (size < tests[cnt].min) |
110 | { |
111 | printf (format: "%zu: %s: size == %zu was enough\n" , |
112 | cnt, tests[cnt].fmt, size); |
113 | result = 1; |
114 | } |
115 | else |
116 | printf (format: "%zu: %s: size == %zu: OK\n" , cnt, tests[cnt].fmt, size); |
117 | |
118 | free (ptr: buf); |
119 | } |
120 | |
121 | struct tm ttm = |
122 | { |
123 | /* Initialize the fields which are needed in the tests. */ |
124 | .tm_mday = 1, |
125 | .tm_hour = 2 |
126 | }; |
127 | const struct |
128 | { |
129 | const char *fmt; |
130 | const char *exp; |
131 | size_t n; |
132 | } ftests[] = |
133 | { |
134 | { "%-e" , "1" , 1 }, |
135 | { "%-k" , "2" , 1 }, |
136 | { "%-l" , "2" , 1 }, |
137 | }; |
138 | #define nftests (sizeof (ftests) / sizeof (ftests[0])) |
139 | for (cnt = 0; cnt < nftests; ++cnt) |
140 | { |
141 | char buf[100]; |
142 | size_t r = strftime (buf, sizeof (buf), ftests[cnt].fmt, &ttm); |
143 | if (r != ftests[cnt].n) |
144 | { |
145 | printf (format: "strftime(\"%s\") returned %zu not %zu\n" , |
146 | ftests[cnt].fmt, r, ftests[cnt].n); |
147 | result = 1; |
148 | } |
149 | if (strcmp (buf, ftests[cnt].exp) != 0) |
150 | { |
151 | printf (format: "strftime(\"%s\") produced \"%s\" not \"%s\"\n" , |
152 | ftests[cnt].fmt, buf, ftests[cnt].exp); |
153 | result = 1; |
154 | } |
155 | } |
156 | |
157 | return result + do_bz18985 (); |
158 | } |
159 | |
160 | #define TEST_FUNCTION do_test () |
161 | #include "../test-skeleton.c" |
162 | |