Browse Source

Add date guessing feature + tests

Yann Weber 7 years ago
parent
commit
fa815adb0c
3 changed files with 211 additions and 1 deletions
  1. 13
    0
      src/include/ttail.h
  2. 79
    1
      src/ttail.c
  3. 119
    0
      tests/ttail_init_check.c

+ 13
- 0
src/include/ttail.h View File

@@ -15,6 +15,11 @@
15 15
 #define TTAIL_FLAG_PREFIX 1
16 16
 #define TTAIL_FLAG_DATE_MIN 2
17 17
 #define TTAIL_FLAG_DATE_MAX 4
18
+#define TTAIL_FLAG_FORMAT 8
19
+#define TTAIL_DEFAULT_FORMATS {"%m", "%A %B %d, %Y %H:%M:%S", "%A", "%B", \
20
+"%m/%d/%y %I %p", "%d,%m,%Y %H:%M", "at %A the %dst of %B in %Y",\
21
+"run job at %I %p,%B %dnd", "%A den %d. %B %Y %H.%M Uhr",\
22
+"%c", "%y/%m/%d", "%Y/%m/%d", "%y-%m-%d", "%Y/%m/%d:%H:%M",NULL}
18 23
 
19 24
 struct _ttail_s
20 25
 {
@@ -58,6 +63,14 @@ int ttail_add_logfile(ttail_t*, const char*);
58 63
  */
59 64
 int ttail_set_prefix(ttail_t*, const char*);
60 65
 
66
+/**@brief Attempt to guess a dateformat
67
+ *@param ttail_t* ttail if manage to guess set the ttail_t.fmt
68
+ *@param const char* date as a dtring
69
+ *@param struct tm* if non NULL will be set to detected date
70
+ *@return -1 if no guess -2 if fmt already set else id in TTAIL_DEFAULT_FORMATS
71
+ */
72
+int ttail_format_guess(ttail_t*, const char*, struct tm*);
73
+
61 74
 void ttail_free(ttail_t*);
62 75
 
63 76
 

+ 79
- 1
src/ttail.c View File

@@ -22,6 +22,8 @@ ttail_t *ttail_init(int argc, char **argv)
22 22
 	res->logfile = NULL;
23 23
 	res->logfile_name = NULL;
24 24
 	res->logfile_sz = 0;
25
+	memset(&(res->date_min), 0, sizeof(struct tm));
26
+	memset(&(res->date_max), 0, sizeof(struct tm));
25 27
 
26 28
 	while(1)
27 29
 	{
@@ -52,7 +54,7 @@ ttail_t *ttail_init(int argc, char **argv)
52 54
 				}
53 55
 				break;
54 56
 			case 'f':
55
-				if(res->fmt)
57
+				if(res->flag & TTAIL_FLAG_FORMAT)
56 58
 				{
57 59
 					fprintf(stderr,"Multiple date format \
58 60
 given\n");
@@ -67,6 +69,7 @@ for date format");
67 69
 					goto ttail_init_err;
68 70
 				}
69 71
 				strcpy(res->fmt, optarg);
72
+				res->flag |= TTAIL_FLAG_FORMAT;
70 73
 
71 74
 				break;
72 75
 			case 'l':
@@ -110,12 +113,26 @@ for date format");
110 113
 		goto ttail_init_err;
111 114
 	}
112 115
 
116
+	/* date min/max processing */
113 117
 	for(c=0;c<c;c++)
114 118
 	{
115 119
 		if(!dates[c])
116 120
 		{
117 121
 			continue;
118 122
 		}
123
+		if(!(res->flag & TTAIL_FLAG_PREFIX))
124
+		{
125
+			/* no format specified */
126
+			ret = ttail_format_guess(res, dates[c],
127
+				c==0?&(res->date_min):&(res->date_max));
128
+			if(res < 0)
129
+			{
130
+				fprintf(stderr, "Unable to guess format for \
131
+date '%s'\n", dates[c]);
132
+				goto ttail_init_err;
133
+			}
134
+			continue;
135
+		}
119 136
 		date = strptime(dates[c], res->fmt, 
120 137
 			c==0?&(res->date_min):&(res->date_max));
121 138
 		if(!date)
@@ -245,6 +262,67 @@ error message");
245 262
 	return -1;
246 263
 }
247 264
 
265
+int ttail_format_guess(ttail_t* t, const char* date_str, struct tm* tm)
266
+{
267
+	int i, res;
268
+	char *res_ret, *ret;
269
+	char *fmt[] = TTAIL_DEFAULT_FORMATS;
270
+	struct tm dte;
271
+	
272
+	memset(&dte, 0, sizeof(struct tm));
273
+
274
+	if(t->flag & TTAIL_FLAG_FORMAT)
275
+	{
276
+		fprintf(stderr, "Format allready set\n");
277
+		return -2;
278
+	}
279
+	res = -1;
280
+	res_ret = NULL;
281
+	i=0;
282
+	while(fmt[i])
283
+	{
284
+		ret = strptime(date_str, fmt[i], &dte);
285
+		if(ret)
286
+		{
287
+			if(!res_ret || strlen(res_ret) > strlen(ret))
288
+			{
289
+				res_ret = ret;
290
+				res = i;
291
+				if(tm)
292
+				{
293
+					memcpy(tm, &dte, sizeof(struct tm));
294
+				}
295
+				if(t->fmt)
296
+				{
297
+					free(t->fmt);
298
+				}
299
+				t->fmt = malloc(
300
+					sizeof(char)*(strlen(fmt[i])+1));
301
+				if(!t->fmt)
302
+				{
303
+					perror("Unable to allocate memory\
304
+for date format");
305
+					t->flag ^= TTAIL_FLAG_FORMAT;
306
+					return -1;
307
+				}
308
+				strcpy(t->fmt, fmt[i]);
309
+				t->flag |= TTAIL_FLAG_FORMAT;
310
+			}
311
+		}
312
+		i++;
313
+	}
314
+	if(!res_ret)
315
+	{
316
+		if(tm)
317
+		{
318
+			memset(tm, 0, sizeof(struct tm));
319
+		}
320
+		return -1;
321
+	}
322
+
323
+	return res;
324
+}
325
+
248 326
 void ttail_free(ttail_t* t)
249 327
 {
250 328
 	size_t i;

+ 119
- 0
tests/ttail_init_check.c View File

@@ -10,7 +10,10 @@ ttail_t *ttail;
10 10
 #define __Fname_sz 5
11 11
 #define FNAME_NO_EXIST 0
12 12
 #define FNAME_EXIST 1
13
+
13 14
 char *fname[__Fname_sz];
15
+/*date formats*/
16
+char *fmt[] = TTAIL_DEFAULT_FORMATS;
14 17
 
15 18
 void teardown_ttail(void)
16 19
 {
@@ -20,6 +23,9 @@ void setup_ttail_empty(void)
20 23
 {
21 24
 	ttail = ttail_init(1, (char**)&"foo");
22 25
 }
26
+/*
27
+ * ttail_add_logfile() tests
28
+ */
23 29
 START_TEST (test_init_empty_logfilename)
24 30
 {
25 31
 	ck_assert_msg(ttail->logfile_name == NULL,
@@ -149,6 +155,9 @@ START_TEST (test_init_multiple_logfilename)
149 155
 }
150 156
 END_TEST
151 157
 
158
+/*
159
+ * ttail_set_prefix() tests
160
+ */
152 161
 START_TEST (test_init_prefix)
153 162
 {
154 163
 	int ret;
@@ -192,11 +201,110 @@ START_TEST (test_init_againbad_prefix)
192 201
 }
193 202
 END_TEST
194 203
 
204
+/*
205
+ * ttail_format_guess() tests
206
+ */
207
+START_TEST (test_init_guess_date)
208
+{
209
+	int ret;
210
+	struct tm tm;
211
+	char res[] = "%Y/%m/%d";
212
+	ret = ttail_format_guess(ttail, "1988/10/22", &tm);
213
+	ck_assert_int_ne(ret, -1);
214
+	ck_assert_str_eq(fmt[ret], res);
215
+	ck_assert(ttail->fmt != NULL);
216
+	ck_assert_str_eq(ttail->fmt, res);
217
+	ck_assert((ttail->flag & TTAIL_FLAG_FORMAT) == TTAIL_FLAG_FORMAT);
218
+	ck_assert_int_eq(tm.tm_year, 88);
219
+	ck_assert_int_eq(tm.tm_mon, 9);
220
+	ck_assert_int_eq(tm.tm_mday, 22);
221
+	ck_assert_int_eq(tm.tm_hour, 0);
222
+	ck_assert_int_eq(tm.tm_min, 0);
223
+	ck_assert_int_eq(tm.tm_sec, 0);
224
+}
225
+END_TEST
226
+
227
+START_TEST (test_init_guess_datetime)
228
+{
229
+	int ret;
230
+	struct tm tm;
231
+	char res[] = "%Y/%m/%d:%H:%M";
232
+	ret = ttail_format_guess(ttail, "1988/10/22:22:10:00", &tm);
233
+	ck_assert_int_ne(ret, -1);
234
+	ck_assert_str_eq(fmt[ret], res);
235
+	ck_assert(ttail->fmt != NULL);
236
+	ck_assert_str_eq(ttail->fmt, res);
237
+	ck_assert((ttail->flag & TTAIL_FLAG_FORMAT) == TTAIL_FLAG_FORMAT);
238
+	ck_assert_int_eq(tm.tm_year, 88);
239
+	ck_assert_int_eq(tm.tm_mon, 9);
240
+	ck_assert_int_eq(tm.tm_mday, 22);
241
+	ck_assert_int_eq(tm.tm_hour, 22);
242
+	ck_assert_int_eq(tm.tm_min, 10);
243
+	ck_assert_int_eq(tm.tm_sec, 0);
244
+}
245
+END_TEST
246
+
247
+START_TEST (test_init_guess_noguess)
248
+{
249
+	int ret;
250
+	struct tm tm;
251
+	ret = ttail_format_guess(ttail, "notadate", &tm);
252
+	ck_assert_int_eq(ret, -1);
253
+	ck_assert(ttail->fmt == NULL);
254
+	ck_assert((ttail->flag & TTAIL_FLAG_FORMAT) == 0);
255
+	ck_assert_int_eq(tm.tm_year, 0);
256
+	ck_assert_int_eq(tm.tm_mon, 0);
257
+	ck_assert_int_eq(tm.tm_mday, 0);
258
+	ck_assert_int_eq(tm.tm_hour, 0);
259
+	ck_assert_int_eq(tm.tm_min, 0);
260
+	ck_assert_int_eq(tm.tm_sec, 0);
261
+}
262
+END_TEST
263
+
264
+START_TEST (test_init_guess_date_notm)
265
+{
266
+	int ret;
267
+	char res[] = "%Y/%m/%d";
268
+	ret = ttail_format_guess(ttail, "1988/10/22", NULL);
269
+	ck_assert_int_ne(ret, -1);
270
+	ck_assert_str_eq(fmt[ret], res);
271
+	ck_assert(ttail->fmt != NULL);
272
+	ck_assert_str_eq(ttail->fmt, res);
273
+	ck_assert((ttail->flag & TTAIL_FLAG_FORMAT) == TTAIL_FLAG_FORMAT);
274
+}
275
+END_TEST
276
+
277
+START_TEST (test_init_guess_noguess_notm)
278
+{
279
+	int ret;
280
+	struct tm tm;
281
+	ret = ttail_format_guess(ttail, "notadate", &tm);
282
+	ck_assert_int_eq(ret, -1);
283
+	ck_assert(ttail->fmt == NULL);
284
+	ck_assert((ttail->flag & TTAIL_FLAG_FORMAT) == 0);
285
+}
286
+END_TEST
287
+
288
+START_TEST (test_init_guess_fmt_set)
289
+{
290
+	int ret;
291
+	struct tm tm;
292
+	char res[] = "%Y/%m/%d";
293
+	ret = ttail_format_guess(ttail, "1988/10/22", NULL);
294
+	ck_assert_int_eq(ret, 11);
295
+	ret = ttail_format_guess(ttail, "1988/10/22", NULL);
296
+	ck_assert_int_eq(ret, -2);
297
+	ck_assert_str_eq(ttail->fmt, res);
298
+	ck_assert((ttail->flag & TTAIL_FLAG_FORMAT) == TTAIL_FLAG_FORMAT);
299
+}
300
+END_TEST
301
+
195 302
 Suite * ttail_init_suite(void)
196 303
 {
197 304
 	Suite *s;
198 305
 	TCase *tc_init_logfile;
199 306
 	TCase *tc_init_prefix;
307
+	TCase *tc_init_fmt_guess;
200 308
 
201 309
 	s = suite_create("ttail init checks");
202 310
 
@@ -218,8 +326,19 @@ Suite * ttail_init_suite(void)
218 326
 	tcase_add_test(tc_init_prefix, test_init_again_prefix);
219 327
 	tcase_add_test(tc_init_prefix, test_init_againbad_prefix);
220 328
 
329
+	tc_init_fmt_guess = tcase_create("date format guess init checks");
330
+	tcase_add_checked_fixture(tc_init_fmt_guess,
331
+		setup_ttail_empty, teardown_ttail);
332
+	tcase_add_test(tc_init_fmt_guess, test_init_guess_date);
333
+	tcase_add_test(tc_init_fmt_guess, test_init_guess_datetime);
334
+	tcase_add_test(tc_init_fmt_guess, test_init_guess_noguess);
335
+	tcase_add_test(tc_init_fmt_guess, test_init_guess_date_notm);
336
+	tcase_add_test(tc_init_fmt_guess, test_init_guess_noguess_notm);
337
+	tcase_add_test(tc_init_fmt_guess, test_init_guess_fmt_set);
338
+
221 339
 	suite_add_tcase(s, tc_init_logfile);
222 340
 	suite_add_tcase(s, tc_init_prefix);
341
+	suite_add_tcase(s, tc_init_fmt_guess);
223 342
 	return s;
224 343
 }
225 344
 

Loading…
Cancel
Save