Browse Source

Logger implementation continuation + tests

Yann Weber 4 years ago
parent
commit
eece95e7a8
3 changed files with 301 additions and 27 deletions
  1. 25
    2
      include/logger.h
  2. 74
    14
      src/logger.c
  3. 202
    11
      tests/check_logger.c

+ 25
- 2
include/logger.h View File

@@ -55,6 +55,11 @@
55 55
 #define PYFCGI_LOGGER_FIELD_MAX 24
56 56
 #define PYFCGI_LOGGER_FMT_PARSE_ERRSZ 64
57 57
 
58
+#define PYFCGI_LOG_DTM_LEN 10
59
+#define PYFCGI_LOG_LVL_LEN 7
60
+#define PYFCGI_LOG_TYP_LEN 7
61
+#define PYFCGI_LOG_PID_LEN 5
62
+
58 63
 #define SYSLOG_syslog syslog
59 64
 #define SYSLOG_vsyslog vsyslog
60 65
 #define SYSLOG_EMERG   LOG_EMERG
@@ -65,8 +70,6 @@
65 70
 #define SYSLOG_NOTICE  LOG_NOTICE
66 71
 #define SYSLOG_INFO    LOG_INFO
67 72
 #define SYSLOG_DEBUG   LOG_DEBUG
68
-static const short SYSLOG_LVLS[8] = {LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
69
-                                     LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG};
70 73
 
71 74
 #undef LOG_EMERG
72 75
 #undef LOG_ALERT
@@ -139,6 +142,15 @@ typedef enum pyfcgi_logger_field_type pyfcgi_logger_field_type_e;
139 142
 typedef struct strftime_args_s strftime_args_t;
140 143
 typedef union pyfcgi_logger_field_args pyfcgi_logger_field_args_u;
141 144
 
145
+
146
+static const short SYSLOG_LVLS[8] = {LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
147
+                                     LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG};
148
+static const char* PYFCGI_LOGGER_LVLNAME[] = {"Emergency", "Alert", "Critical",
149
+                                              "Error", "Warning", "Notice",
150
+					      "Info", "Debug"};
151
+
152
+static const char* PYFCGI_LOGGER_TYPNAME[] = {"Global", "Access", "Internal",
153
+                                              "Worker", "Master"};
142 154
 /**@brief Logger configuration
143 155
  * @ingroup conf_logger
144 156
  */
@@ -299,6 +311,11 @@ int pyfcgi_logger_parse_field(const char**, const char *,
299 311
                               pyfcgi_logger_fmt_field_t*,
300 312
                               char[PYFCGI_LOGGER_FMT_PARSE_ERRSZ]);
301 313
 
314
+/**@brief Free allocated memory in given field
315
+ * @param pyfcgi_logger_fmt_field_t* field to free
316
+ */
317
+void pyfcgi_logger_field_free(pyfcgi_logger_fmt_field_t*);
318
+
302 319
 /**@brief Given a field pointer return the size option incrementing
303 320
  * ptr
304 321
  * @warning do not check if the next character is OK, the caller has to
@@ -319,6 +336,12 @@ int pyfcgi_logger_parse_field_sz(const char**, size_t*);
319 336
  */
320 337
 int pyfcgi_logger_parse_field_dtfmt(const char**, char**);
321 338
 
339
+/**@brief Return a str repr of given loglevel
340
+ * @warning returned pointer must NOT be freed or modified
341
+ * @return The loglevel name or NULL if error
342
+ */
343
+const char* pyfcgi_logger_value_level(short);
344
+const char* pyfcgi_logger_value_facility(short);
322 345
 
323 346
 /**@brief Open a logger
324 347
  * @param pyfcgi_logger_t

+ 74
- 14
src/logger.c View File

@@ -124,7 +124,8 @@ int pyfcgi_logger_parse_format(const char* fmt,
124 124
 		}
125 125
 		str_start = ptr;
126 126
 		while(*ptr && *ptr != '{' && *(ptr+1) != '{')
127
-		{
127
+		{ // handling const chr fields
128
+			//TODO : issue warning/error when unescaped '}' found
128 129
 			if(!cur_field->type)
129 130
 			{
130 131
 				cur_field->type = pyfcgi_logger_field_const;
@@ -186,7 +187,7 @@ int pyfcgi_logger_parse_field(const char** ptr, const char *start,
186 187
 	
187 188
 	const char *str_start, *field_start;
188 189
 	int ret;
189
-	char **name, **format;
190
+	char **name, *cname, **format;
190 191
 	size_t default_len;
191 192
 	pyfcgi_logger_field_type_e *type;
192 193
 	char *field_names[] = {"datetime", "level", "facility", "pid", "ident",
@@ -202,33 +203,37 @@ int pyfcgi_logger_parse_field(const char** ptr, const char *start,
202 203
 	type = field_types;
203 204
 	while(*name)
204 205
 	{
205
-		if(**name != **ptr)
206
+		cname = *name;
207
+		if(*cname != **ptr)
206 208
 		{
207 209
 			name++;
208 210
 			type++;
209 211
 			continue;
210 212
 		}
211 213
 		// Name found ?
212
-		while(**ptr && **name && **ptr != ':' && **ptr != '}')
214
+		while(**ptr && *cname && **ptr != ':' && **ptr != '}' &&
215
+		      **ptr == *cname)
213 216
 		{
214
-			if(**ptr != **name)
215
-			{
216
-				break;
217
-			}
218 217
 			(*ptr)++;
219
-			(*name)++;
218
+			cname++;
220 219
 		}
221 220
 		if(**ptr == ':' || **ptr == '}')
222 221
 		{
223 222
 			cur_field->type = *type;
223
+			break;
224 224
 		}
225 225
 		else
226 226
 		{
227
+			*name = field_names[6]; // NULL
228
+			break;
229
+		}
230
+	}
231
+	if(!name)
232
+	{
227 233
 			snprintf(fail_reason, PYFCGI_LOGGER_FMT_PARSE_ERRSZ,
228 234
 				 "unknown field type '%s' chr %ld",
229 235
 				 str_start, str_start - start);
230 236
 			return 1;
231
-		}
232 237
 	}
233 238
 	if(**ptr == ':') { (*ptr)++; } // next option
234 239
 	if(pyfcgi_logger_parse_field_sz(ptr, &(cur_field->len)))
@@ -244,7 +249,7 @@ int pyfcgi_logger_parse_field(const char** ptr, const char *start,
244 249
 	switch(cur_field->type)
245 250
 	{
246 251
 		case pyfcgi_logger_field_datetime:
247
-			default_len = 10;
252
+			default_len = PYFCGI_LOG_DTM_LEN;
248 253
 			cur_field->val = (void*)strftime;
249 254
 			format = &(cur_field->args.datetime.format);
250 255
 			ret = pyfcgi_logger_parse_field_dtfmt(ptr,format);
@@ -253,16 +258,20 @@ int pyfcgi_logger_parse_field(const char** ptr, const char *start,
253 258
 			}
254 259
 			break;
255 260
 		case pyfcgi_logger_field_level:
256
-			default_len = 7;
261
+			default_len = PYFCGI_LOG_LVL_LEN;
262
+			cur_field->val = (void*)pyfcgi_logger_value_level;
257 263
 			break;
258 264
 		case pyfcgi_logger_field_facility:
259
-			default_len = 6;
265
+			default_len = PYFCGI_LOG_TYP_LEN;
266
+			cur_field->val = (void*)pyfcgi_logger_value_facility;
260 267
 			break;
261 268
 		case pyfcgi_logger_field_pid:
262
-			default_len = 5;
269
+			default_len = PYFCGI_LOG_PID_LEN;
270
+			cur_field->val = &(PyFCGI_conf.context.pid);
263 271
 			break;
264 272
 		case pyfcgi_logger_field_ident:
265 273
 			default_len = 0;
274
+			cur_field->val = &(PyFCGI_conf.logs.ident);
266 275
 			break;
267 276
 		case pyfcgi_logger_field_msg:
268 277
 			cur_field->known_length = 0;
@@ -281,6 +290,34 @@ int pyfcgi_logger_parse_field(const char** ptr, const char *start,
281 290
 	return 0;
282 291
 }
283 292
 
293
+void pyfcgi_logger_field_free(pyfcgi_logger_fmt_field_t* field)
294
+{
295
+	switch(field->type)
296
+	{
297
+		case pyfcgi_logger_field_const:
298
+			if(field->val)
299
+			{
300
+				free(field->val);
301
+			}
302
+			break;
303
+		case pyfcgi_logger_field_datetime:
304
+			if(field->args.datetime.format)
305
+			{
306
+				free(field->args.datetime.format);
307
+			}
308
+			break;
309
+		case pyfcgi_logger_field_null:
310
+		case pyfcgi_logger_field_level:
311
+		case pyfcgi_logger_field_facility:
312
+		case pyfcgi_logger_field_pid:
313
+		case pyfcgi_logger_field_ppid:
314
+		case pyfcgi_logger_field_ident:
315
+		case pyfcgi_logger_field_msg:
316
+			break;
317
+	}
318
+}
319
+
320
+
284 321
 int pyfcgi_logger_parse_field_dtfmt(const char** ptr, char** format)
285 322
 {
286 323
 	const char *fmt;
@@ -330,6 +367,29 @@ int pyfcgi_logger_parse_field_sz(const char **ptr, size_t *size)
330 367
 	return 0;
331 368
 }
332 369
 
370
+const char* pyfcgi_logger_value_level(short lvl)
371
+{
372
+	short idx;
373
+	idx = (lvl & 0xF0) >> 4;
374
+	if(idx < 0 || idx >= sizeof(PYFCGI_LOGGER_LVLNAME))
375
+	{
376
+		return NULL;
377
+	}
378
+	return PYFCGI_LOGGER_LVLNAME[idx];
379
+}
380
+
381
+
382
+const char* pyfcgi_logger_value_facility(short typ)
383
+{
384
+	short idx;
385
+	idx = typ & 0x0F;
386
+	if(idx < 0 || idx >= sizeof(PYFCGI_LOGGER_TYPNAME))
387
+	{
388
+		return NULL;
389
+	}
390
+	return PYFCGI_LOGGER_TYPNAME[idx];
391
+}
392
+
333 393
 int pyfcgi_logger_open(pyfcgi_logger_t *logger)
334 394
 {
335 395
 	if( (logger->fd = open(logger->filename,

+ 202
- 11
tests/check_logger.c View File

@@ -48,6 +48,7 @@ START_TEST(test_logger_parse_field_dtfmt_default)
48 48
 	ck_assert_int_eq(ret, 0);
49 49
 	ck_assert_str_eq(fmt, PYFCGI_LOGGER_TIME_FMT_DEFAULT);
50 50
 	ck_assert_ptr_eq(ptr, orig+1);
51
+	free(fmt);
51 52
 }
52 53
 END_TEST
53 54
 
@@ -95,7 +96,7 @@ START_TEST(test_logger_parse_field_datetime_default)
95 96
 		ck_assert_int_eq(ret, 0);
96 97
 		ck_assert_int_eq(field.type, pyfcgi_logger_field_datetime);
97 98
 		ck_assert_int_ne(field.known_length, 0);
98
-		ck_assert_int_eq(field.len, 10);
99
+		ck_assert_int_eq(field.len, PYFCGI_LOG_DTM_LEN);
99 100
 		ck_assert_ptr_eq(field.val, strftime);
100 101
 		ck_assert_str_eq(field.args.datetime.format,
101 102
 		                 PYFCGI_LOGGER_TIME_FMT_DEFAULT);
@@ -128,15 +129,43 @@ START_TEST(test_logger_parse_field_sz)
128 129
 }
129 130
 END_TEST
130 131
 
131
-START_TEST(test_logger_parse_field_Tdatetime)
132
+START_TEST(test_logger_parse_field_dtfmt)
133
+{
134
+	int ret;
135
+	size_t len;
136
+	char **val, **ptr, *fmt;
137
+	char *_vals[] = {"%fdc}", "123}", "4}}foo}", NULL};
138
+
139
+	val = _vals;
140
+	while(*val)
141
+	{
142
+		ptr = val;
143
+		len = strlen(*val);
144
+
145
+		ret = pyfcgi_logger_parse_field_dtfmt((const char**)&ptr, &fmt);
146
+		*val[len-1] = '\0'; //deleting leading '}' to get expected result
147
+		ck_assert_int_eq(ret, 0);
148
+		ck_assert_ptr_ne(fmt, *val);
149
+		ck_assert_str_eq(fmt, *val);
150
+		ck_assert_ptr_eq(ptr, *val+len-1);
151
+		free(fmt);
152
+		val++;
153
+	}
154
+
155
+}
156
+END_TEST
157
+
158
+START_TEST(test_logger_parse_field_datetime)
132 159
 {
133 160
 	int ret, *len;
134 161
 	char *ptr, **orig, **fmt, err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
135 162
 	pyfcgi_logger_fmt_field_t field;
136 163
 	char *vals[] = {"datetime:42}", "datetime::%s%F}",
137
-	                "datetime:42:COUCOU}", NULL};
138
-	int _len[] = {42, 10, 42};
139
-	char *_fmt[] = {PYFCGI_LOGGER_TIME_FMT_DEFAULT, "%s%F", "COUCOU"};
164
+	                "datetime:42:COUCOU}",
165
+			"dat:32:FOO}", "d::BAR}", NULL};
166
+	int _len[] = {42, PYFCGI_LOG_DTM_LEN, 42, 32, PYFCGI_LOG_DTM_LEN};
167
+	char *_fmt[] = {PYFCGI_LOGGER_TIME_FMT_DEFAULT, "%s%F", "COUCOU", "FOO",
168
+	                "BAR"};
140 169
 
141 170
 	memset(&field, 0, sizeof(pyfcgi_logger_fmt_field_t));
142 171
 	
@@ -147,7 +176,6 @@ START_TEST(test_logger_parse_field_Tdatetime)
147 176
 	{
148 177
 		ptr = *orig;
149 178
 
150
-dprintf(2, "ORIG='%s'\n", *orig);
151 179
 		ret = pyfcgi_logger_parse_field((const char**)&ptr,
152 180
 		                                (const char*)ptr, &field,
153 181
 						err);
@@ -169,6 +197,162 @@ dprintf(2, "ORIG='%s'\n", *orig);
169 197
 }
170 198
 END_TEST
171 199
 
200
+START_TEST(test_logger_parse_field_level)
201
+{
202
+	int ret;
203
+	char **val, **ptr;
204
+	char err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
205
+	char *vals[] = {"level}", "l}", "leve}", NULL};
206
+	pyfcgi_logger_fmt_field_t field;
207
+
208
+	val = vals;
209
+	memset(&field, 0, sizeof(pyfcgi_logger_fmt_field_t));
210
+
211
+	while(*val)
212
+	{
213
+		ptr = val;
214
+		ret = pyfcgi_logger_parse_field((const char**)ptr,
215
+		                                (const char*)*ptr, &field,
216
+						err);
217
+		if(ret)
218
+		{
219
+			dprintf(2, "ERROR : '%s'\n", err);
220
+		}
221
+		ck_assert_int_eq(ret, 0);
222
+		ck_assert_int_eq(field.type, pyfcgi_logger_field_level);
223
+		ck_assert_int_ne(field.known_length, 0);
224
+		ck_assert_int_eq(field.len, PYFCGI_LOG_LVL_LEN);
225
+		ck_assert_ptr_eq(field.val, pyfcgi_logger_value_level);
226
+		val++;
227
+	}
228
+}
229
+END_TEST
230
+
231
+START_TEST(test_logger_parse_field_facility)
232
+{
233
+	int ret;
234
+	char **val, **ptr;
235
+	char err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
236
+	char *vals[] = {"facility}", "f}", "fac}", NULL};
237
+	pyfcgi_logger_fmt_field_t field;
238
+
239
+	val = vals;
240
+	memset(&field, 0, sizeof(pyfcgi_logger_fmt_field_t));
241
+
242
+	while(*val)
243
+	{
244
+		ptr = val;
245
+		ret = pyfcgi_logger_parse_field((const char**)ptr,
246
+		                                (const char*)*ptr, &field,
247
+						err);
248
+		if(ret)
249
+		{
250
+			dprintf(2, "ERROR : '%s'\n", err);
251
+		}
252
+		ck_assert_int_eq(ret, 0);
253
+		ck_assert_int_eq(field.type, pyfcgi_logger_field_facility);
254
+		ck_assert_int_ne(field.known_length, 0);
255
+		ck_assert_int_eq(field.len, PYFCGI_LOG_TYP_LEN);
256
+		ck_assert_ptr_eq(field.val, pyfcgi_logger_value_facility);
257
+		val++;
258
+	}
259
+}
260
+END_TEST
261
+
262
+START_TEST(test_logger_parse_field_pid)
263
+{
264
+	int ret;
265
+	char **val, **ptr;
266
+	char err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
267
+	char *vals[] = {"pid}", "p}", "pi}", NULL};
268
+	pyfcgi_logger_fmt_field_t field;
269
+
270
+	val = vals;
271
+	memset(&field, 0, sizeof(pyfcgi_logger_fmt_field_t));
272
+
273
+	while(*val)
274
+	{
275
+		ptr = val;
276
+		ret = pyfcgi_logger_parse_field((const char**)ptr,
277
+		                                (const char*)*ptr, &field,
278
+						err);
279
+		if(ret)
280
+		{
281
+			dprintf(2, "ERROR : '%s'\n", err);
282
+		}
283
+		ck_assert_int_eq(ret, 0);
284
+		ck_assert_int_eq(field.type, pyfcgi_logger_field_pid);
285
+		ck_assert_int_ne(field.known_length, 0);
286
+		ck_assert_int_eq(field.len, PYFCGI_LOG_PID_LEN);
287
+		ck_assert_ptr_eq(field.val, (&PyFCGI_conf.context.pid));
288
+		val++;
289
+	}
290
+}
291
+END_TEST
292
+
293
+START_TEST(test_logger_parse_field_ident)
294
+{
295
+	int ret;
296
+	char **val, **ptr;
297
+	char err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
298
+	char *vals[] = {"ident}", "i}", "id}", NULL};
299
+	pyfcgi_logger_fmt_field_t field;
300
+
301
+	val = vals;
302
+	memset(&field, 0, sizeof(pyfcgi_logger_fmt_field_t));
303
+
304
+	while(*val)
305
+	{
306
+		ptr = val;
307
+		ret = pyfcgi_logger_parse_field((const char**)ptr,
308
+		                                (const char*)*ptr, &field,
309
+						err);
310
+		if(ret)
311
+		{
312
+			dprintf(2, "ERROR : '%s'\n", err);
313
+		}
314
+		ck_assert_int_eq(ret, 0);
315
+		ck_assert_int_eq(field.type, pyfcgi_logger_field_ident);
316
+		ck_assert_int_ne(field.known_length, 0);
317
+		ck_assert_int_eq(field.len, 0);
318
+		ck_assert_ptr_eq(field.val, (&PyFCGI_conf.logs.ident));
319
+		val++;
320
+	}
321
+}
322
+END_TEST
323
+
324
+
325
+START_TEST(test_logger_parse_field_msg)
326
+{
327
+	int ret;
328
+	char **val, **ptr;
329
+	char err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
330
+	char *vals[] = {"msg}", "m}", "ms}", NULL};
331
+	pyfcgi_logger_fmt_field_t field;
332
+
333
+	val = vals;
334
+	memset(&field, 0, sizeof(pyfcgi_logger_fmt_field_t));
335
+
336
+	while(*val)
337
+	{
338
+		ptr = val;
339
+		ret = pyfcgi_logger_parse_field((const char**)ptr,
340
+		                                (const char*)*ptr, &field,
341
+						err);
342
+		if(ret)
343
+		{
344
+			dprintf(2, "ERROR : '%s'\n", err);
345
+		}
346
+		ck_assert_int_eq(ret, 0);
347
+		ck_assert_int_eq(field.type, pyfcgi_logger_field_msg);
348
+		ck_assert_int_eq(field.known_length, 0);
349
+		ck_assert_int_eq(field.len, 0);
350
+		ck_assert_ptr_eq(field.val, NULL);
351
+		val++;
352
+	}
353
+}
354
+END_TEST
355
+
172 356
 Suite * logger_suite(void)
173 357
 {
174 358
 	Suite *s;
@@ -181,15 +365,20 @@ Suite * logger_suite(void)
181 365
 	//tcase_add_test(tc_init, test_logger_format_add);
182 366
 	suite_add_tcase(s, tc_init);
183 367
 
184
-	tc_fmt_default = tcase_create("Logger format default values");
368
+	tc_fmt_default = tcase_create("Logger format parsing default values");
185 369
 	tcase_add_test(tc_fmt_default, test_logger_parse_field_dtfmt_default);
186 370
 	tcase_add_test(tc_fmt_default, test_logger_parse_field_sz_default);
187 371
 	tcase_add_test(tc_fmt_default, test_logger_parse_field_datetime_default);
188 372
 	suite_add_tcase(s, tc_fmt_default);
189 373
 
190
-	tc_fmt = tcase_create("Logger format");
191
-	tcase_add_test(tc_fmt_default, test_logger_parse_field_sz);
192
-	tcase_add_test(tc_fmt_default, test_logger_parse_field_Tdatetime);
374
+	tc_fmt = tcase_create("Logger format parsing");
375
+	tcase_add_test(tc_fmt, test_logger_parse_field_sz);
376
+	tcase_add_test(tc_fmt, test_logger_parse_field_datetime);
377
+	tcase_add_test(tc_fmt, test_logger_parse_field_level);
378
+	tcase_add_test(tc_fmt, test_logger_parse_field_facility);
379
+	tcase_add_test(tc_fmt, test_logger_parse_field_pid);
380
+	tcase_add_test(tc_fmt, test_logger_parse_field_ident);
381
+	tcase_add_test(tc_fmt, test_logger_parse_field_msg);
193 382
 	suite_add_tcase(s, tc_fmt);
194 383
 
195 384
 	return s;
@@ -205,7 +394,9 @@ int main(void)
205 394
 	sr = srunner_create(s);
206 395
 	
207 396
 	//srunner_set_fork_status(sr, CK_NOFORK);
208
-	srunner_run_all(sr, CK_NORMAL);
397
+	//srunner_run_all(sr, CK_NORMAL);
398
+	//srunner_run_all(sr, CK_ENV);
399
+	srunner_run_all(sr, CK_VERBOSE);
209 400
 	nfailed = srunner_ntests_failed(sr);
210 401
 	srunner_free(sr);
211 402
 	return (!nfailed)?EXIT_SUCCESS:EXIT_FAILURE;

Loading…
Cancel
Save