xref: /Universal-ctags/libreadtags/tests/test-api-tagsFind.c (revision 0e675dcc44e62ca4628330a3e983e7b45eb28fd2)
1 /*
2 *   Copyright (c) 2020, Masatake YAMATO
3 *
4 *   This source code is released into the public domain.
5 *
6 *   Testing tagsFind() and tagsFindNext() API functions
7 */
8 
9 #include "readtags.h"
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 
16 
17 struct expectation {
18 	char *name;
19 	char *file;
20 	char *pattern;
21 	char *kind;
22 	char *scope_kind;
23 	char *scope_name;
24 	char *typeref;
25 	int fileScope;
26 
27 	tagResult result;
28 	int       err;
29 };
30 
31 #define COUNT(x) (sizeof(x)/sizeof(x[0]))
32 
33 enum extraTest { TESTX_NO_REMAIN, TESTX_INVALID_ARG };
34 
35 static int
check_finding0(tagFile * t,const char * name,const int options,struct expectation * expectations,int count,enum extraTest xtest)36 check_finding0 (tagFile *t, const char *name, const int options,
37 				struct expectation *expectations, int count, enum extraTest xtest)
38 {
39 	tagEntry e;
40 	struct expectation *x;
41 	int err;
42 
43 	for (int i = 0; i < count; i++)
44 	{
45 		fprintf (stderr, "[%d/%d] finding \"%s\" (%d)...", i + 1, count, name, options);
46 		tagResult r = (i == 0)
47 			? tagsFind (t, &e, name, options)
48 			: tagsFindNext (t, &e);
49 		x = expectations + i;
50 		if (r == TagSuccess)
51 		{
52 			if (x->result == TagFailure)
53 			{
54 				fprintf (stderr, "found unexpectedly\n");
55 				return 1;
56 			}
57 			else
58 				fprintf (stderr, "found as expected\n");
59 		}
60 		else
61 		{
62 			if (x->result == TagFailure)
63 			{
64 				err = tagsGetErrno (t);
65 				if (err == x->err)
66 				{
67 					if (err == 0)
68 						fprintf (stderr, "not found, and it is expected\n");
69 					else
70 						fprintf (stderr, "error as expected: %d\n", err);
71 					continue;
72 				}
73 				else
74 				{
75 					fprintf (stderr, "error number doesn't match: %d (expected: %d)\n",
76 							 err, x->err);
77 					return 1;
78 				}
79 			}
80 			else
81 			{
82 				if ((err = tagsGetErrno (t)))
83 					fprintf (stderr, "error: %d\n", err);
84 				else
85 					fprintf (stderr, "not found\n");
86 				return 1;
87 			}
88 		}
89 
90 		fprintf (stderr, "checking name field...");
91 		if (!(e.name && strcmp (x->name, e.name) == 0))
92 		{
93 			fprintf (stderr, "unexpected: %s\n", e.name? e.name: "<NULL>");
94 			return 1;
95 		}
96 		fprintf (stderr, "ok\n");
97 
98 		fprintf (stderr, "checking file field...");
99 		if (!(e.file && strcmp (x->file, e.file) == 0))
100 		{
101 			fprintf (stderr, "unexpected\n");
102 			return 1;
103 		}
104 		fprintf (stderr, "ok\n");
105 
106 		fprintf (stderr, "checking pattern field...");
107 		if (!(e.address.pattern && strcmp (x->pattern, e.address.pattern) == 0))
108 		{
109 			fprintf (stderr, "unexpected: %s\n",
110 					 e.address.pattern? e.address.pattern: "<NULL>");
111 			return 1;
112 		}
113 		fprintf (stderr, "ok\n");
114 
115 		fprintf (stderr, "checking kind field...");
116 		if (!(e.kind && strcmp (x->kind, e.kind) == 0))
117 		{
118 			fprintf (stderr, "unexpected\n");
119 			return 1;
120 		}
121 		fprintf (stderr, "ok\n");
122 
123 		if (x->scope_kind)
124 		{
125 			fprintf (stderr, "checking scope field...");
126 			const char *scope = tagsField (&e, x->scope_kind);
127 			if (scope == NULL || strcmp (scope, x->scope_name) != 0)
128 			{
129 				fprintf (stderr, "unexpected: %s\n", scope? scope: "<NULL>");
130 				return 1;
131 			}
132 			fprintf (stderr, "ok\n");
133 		}
134 
135 		if (x->typeref)
136 		{
137 			fprintf (stderr, "checking typeref field...");
138 			const char *typeref = tagsField (&e, "typeref");
139 			if (typeref == NULL || strcmp (typeref, x->typeref) != 0)
140 			{
141 				fprintf (stderr, "unexpected: %s\n", typeref? typeref: "<NULL>");
142 				return 1;
143 			}
144 			fprintf (stderr, "ok\n");
145 		}
146 
147 		fprintf (stderr, "checking file field...");
148 		if (x->fileScope != e.fileScope)
149 		{
150 			fprintf (stderr, "unexpected\n");
151 			return 1;
152 		}
153 		fprintf (stderr, "ok\n");
154 	}
155 
156 	if (xtest == TESTX_NO_REMAIN)
157 	{
158 		fprintf (stderr, "verifying no remain....");
159 		if (tagsFindNext (t, &e) == TagSuccess)
160 		{
161 			fprintf (stderr, "still existing\n");
162 			return 1;
163 		}
164 		else if ((err = tagsGetErrno (t)))
165 		{
166 			fprintf (stderr, "unexpected error: %d\n", err);
167 			return 1;
168 		}
169 		fprintf (stderr, "ok\n");
170 	}
171 	else if (xtest == TESTX_NO_REMAIN)
172 	{
173 		fprintf (stderr, "call tagsFindNext after getting an error....");
174 		if (tagsFindNext (t, &e) == TagSuccess)
175 		{
176 			fprintf (stderr, "unexpectedly successful\n");
177 			return 1;
178 		}
179 
180 		err = tagsGetErrno (t);
181 		if (err != TagErrnoInvalidArgument)
182 		{
183 			fprintf (stderr, "errer number doesn't match: %d (expected: %d)\n",
184 					 err, TagErrnoInvalidArgument);
185 			return 1;
186 		}
187 		fprintf (stderr, "get TagErrnoInvalidArgument expectedly\n");
188 	}
189 
190 	return 0;
191 }
192 
193 static int
check_finding(const char * tags,const char * name,const int options,struct expectation * expectations,int count,enum extraTest xtest)194 check_finding (const char *tags, const char *name, const int options,
195 			   struct expectation *expectations, int count, enum extraTest xtest)
196 {
197 	tagFile *t;
198 	tagFileInfo info;
199 
200 	fprintf (stderr, "opening %s...", tags);
201 	t = tagsOpen (tags, &info);
202 	if (!t)
203 	{
204 		fprintf (stderr, "unexpected result (t: %p, opened: %d, error_number: %d)\n",
205 				 t, info.status.opened, info.status.error_number);
206 		return 1;
207 	}
208 	fprintf (stderr, "ok\n");
209 
210 	if (check_finding0 (t, name, options, expectations, count, xtest) != 0)
211 		return 1;
212 
213 	fprintf (stderr, "closing the tag file...");
214 	if (tagsClose (t) != TagSuccess)
215 	{
216 		fprintf (stderr, "unexpected result\n");
217 		return 1;
218 	}
219 	fprintf (stderr, "ok\n");
220 	return 0;
221 }
222 
223 int
main(void)224 main (void)
225 {
226 	char *srcdir = getenv ("srcdir");
227 	if (srcdir)
228 	{
229 		if (chdir (srcdir) == -1)
230 		{
231 			perror ("chdir");
232 			return 99;
233 		}
234 	}
235 
236 	/*
237 	 * sorted=yes
238 	 */
239 	const char *tags_sorted_yes = "./duplicated-names--sorted-yes.tags";
240 	struct expectation sorted_yes_FULLMATCH_OBSERVECASE [] = {
241 		{
242 			.name = "n",
243 			.file = "input.c",
244 			.pattern = "/^		int n;$/",
245 			.kind = "l",
246 			.scope_kind = "function",
247 			.scope_name = "main",
248 			.typeref = "typename:int",
249 			.fileScope = 1,
250 			.result = TagSuccess,
251 		},
252 		{
253 			.name = "n",
254 			.file = "input.c",
255 			.pattern = "/^	for (int n = 0; n < 1; n++)$/",
256 			.kind = "l",
257 			.scope_kind = "function",
258 			.scope_name = "main",
259 			.typeref = "typename:int",
260 			.fileScope = 1,
261 			.result = TagSuccess,
262 		},
263 		{
264 			.name = "n",
265 			.file = "input.c",
266 			.pattern = "/^	int n;$/",
267 			.kind = "m",
268 			.scope_kind = "struct",
269 			.scope_name = "n",
270 			.typeref = "typename:int",
271 			.fileScope = 1,
272 			.result = TagSuccess,
273 		},
274 		{
275 			.name = "n",
276 			.file = "input.c",
277 			.pattern = "/^int main(int n)$/",
278 			.kind = "z",
279 			.scope_kind = "function",
280 			.scope_name = "main",
281 			.typeref = "typename:int",
282 			.fileScope = 1,
283 			.result = TagSuccess,
284 		},
285 		{
286 			.name = "n",
287 			.file = "input.c",
288 			.pattern = "/^struct n {$/",
289 			.kind = "s",
290 			.scope_kind = NULL,
291 			.scope_name = NULL,
292 			.typeref = NULL,
293 			.fileScope = 1,
294 			.result = TagSuccess,
295 		},
296 		{
297 			.name = "n",
298 			.file = "input.c",
299 			.pattern = "/^typedef int n;$/",
300 			.kind = "t",
301 			.scope_kind = NULL,
302 			.scope_name = NULL,
303 			.typeref = "typename:int",
304 			.fileScope = 1,
305 			.result = TagSuccess,
306 		},
307 	};
308 
309 	struct expectation sorted_yes_FULLMATCH_IGNORECASE [COUNT(sorted_yes_FULLMATCH_OBSERVECASE) + 1] = {
310 		[0] = {
311 			.name = "N",
312 			.file = "input.c",
313 			.pattern = "/^int N;$/",
314 			.kind = "v",
315 			.scope_kind = NULL,
316 			.scope_name = NULL,
317 			.typeref = "typename:int",
318 			.fileScope = 0,
319 			.result = TagSuccess,
320 		},
321 	};
322 	for (int i = 0; i < COUNT(sorted_yes_FULLMATCH_OBSERVECASE); i++)
323 		sorted_yes_FULLMATCH_IGNORECASE [i + 1] = sorted_yes_FULLMATCH_OBSERVECASE [i];
324 
325 	struct expectation sorted_yes_PARTIALMATCH_OBSERVECASE [] = {
326 		{
327 			.name = "m",
328 			.file = "input.c",
329 			.pattern = "/^int m;$/",
330 			.kind = "v",
331 			.scope_kind = NULL,
332 			.scope_name = NULL,
333 			.typeref = "typename:int",
334 			.fileScope = 0,
335 			.result = TagSuccess,
336 		},
337 		{
338 			.name = "main",
339 			.file = "input.c",
340 			.pattern = "/^int main(int n)$/",
341 			.kind = "f",
342 			.scope_kind = NULL,
343 			.scope_name = NULL,
344 			.typeref = "typename:int",
345 			.fileScope = 0,
346 			.result = TagSuccess,
347 		},
348 	};
349 
350 	struct expectation sorted_yes_PARTIALMATCH_IGNORECASE [COUNT(sorted_yes_PARTIALMATCH_OBSERVECASE) + 1] = {
351 		[0] = {
352 			.name = "M",
353 			.file = "input.c",
354 			.pattern = "/^int M (void) { return 0; }$/",
355 			.kind = "f",
356 			.scope_kind = NULL,
357 			.scope_name = NULL,
358 			.typeref = "typename:int",
359 			.fileScope = 0,
360 			.result = TagSuccess,
361 		},
362 	};
363 	for (int i = 0; i < COUNT(sorted_yes_PARTIALMATCH_OBSERVECASE); i++)
364 		sorted_yes_PARTIALMATCH_IGNORECASE [i + 1] = sorted_yes_PARTIALMATCH_OBSERVECASE [i];
365 
366 	if (check_finding (tags_sorted_yes, "n", TAG_FULLMATCH|TAG_OBSERVECASE,
367 					   sorted_yes_FULLMATCH_OBSERVECASE, COUNT(sorted_yes_FULLMATCH_OBSERVECASE),
368 					   TESTX_NO_REMAIN) != 0)
369 		return 1;
370 
371 	if (check_finding (tags_sorted_yes, "n", TAG_FULLMATCH|TAG_IGNORECASE,
372 					   sorted_yes_FULLMATCH_IGNORECASE, COUNT(sorted_yes_FULLMATCH_IGNORECASE),
373 					   TESTX_NO_REMAIN) != 0)
374 		return 1;
375 
376 	if (check_finding (tags_sorted_yes, "m", TAG_PARTIALMATCH|TAG_OBSERVECASE,
377 					   sorted_yes_PARTIALMATCH_OBSERVECASE, COUNT(sorted_yes_PARTIALMATCH_OBSERVECASE),
378 					   TESTX_NO_REMAIN) != 0)
379 		return 1;
380 
381 	if (check_finding (tags_sorted_yes, "m", TAG_PARTIALMATCH|TAG_IGNORECASE,
382 					   sorted_yes_PARTIALMATCH_IGNORECASE, COUNT(sorted_yes_PARTIALMATCH_IGNORECASE),
383 					   TESTX_NO_REMAIN) != 0)
384 		return 1;
385 
386 
387 	/*
388 	 * sorted=no
389 	 */
390 	const char *tags_sorted_no = "./duplicated-names--sorted-no.tags";
391 	struct expectation sorted_no_FULLMATCH_OBSERVECASE [] = {
392 		{
393 			.name = "n",
394 			.file = "input.c",
395 			.pattern = "/^struct n {$/",
396 			.kind = "s",
397 			.scope_kind = NULL,
398 			.scope_name = NULL,
399 			.typeref = NULL,
400 			.fileScope = 1,
401 			.result = TagSuccess,
402 		},
403 		{
404 			.name = "n",
405 			.file = "input.c",
406 			.pattern = "/^	int n;$/",
407 			.kind = "m",
408 			.scope_kind = "struct",
409 			.scope_name = "n",
410 			.typeref = "typename:int",
411 			.fileScope = 1,
412 			.result = TagSuccess,
413 		},
414 		{
415 			.name = "n",
416 			.file = "input.c",
417 			.pattern = "/^typedef int n;$/",
418 			.kind = "t",
419 			.scope_kind = NULL,
420 			.scope_name = NULL,
421 			.typeref = "typename:int",
422 			.fileScope = 1,
423 			.result = TagSuccess,
424 		},
425 		{
426 			.name = "n",
427 			.file = "input.c",
428 			.pattern = "/^int main(int n)$/",
429 			.kind = "z",
430 			.scope_kind = "function",
431 			.scope_name = "main",
432 			.typeref = "typename:int",
433 			.fileScope = 1,
434 			.result = TagSuccess,
435 		},
436 		{
437 			.name = "n",
438 			.file = "input.c",
439 			.pattern = "/^	for (int n = 0; n < 1; n++)$/",
440 			.kind = "l",
441 			.scope_kind = "function",
442 			.scope_name = "main",
443 			.typeref = "typename:int",
444 			.fileScope = 1,
445 			.result = TagSuccess,
446 		},
447 		{
448 			.name = "n",
449 			.file = "input.c",
450 			.pattern = "/^		int n;$/",
451 			.kind = "l",
452 			.scope_kind = "function",
453 			.scope_name = "main",
454 			.typeref = "typename:int",
455 			.fileScope = 1,
456 			.result = TagSuccess,
457 		},
458 	};
459 
460 	struct expectation sorted_no_FULLMATCH_IGNORECASE [COUNT(sorted_no_FULLMATCH_OBSERVECASE) + 1] = {
461 		[0] = {
462 			.name = "N",
463 			.file = "input.c",
464 			.pattern = "/^int N;$/",
465 			.kind = "v",
466 			.scope_kind = NULL,
467 			.scope_name = NULL,
468 			.typeref = "typename:int",
469 			.fileScope = 0,
470 			.result = TagSuccess,
471 		},
472 	};
473 	for (int i = 0; i < COUNT(sorted_no_FULLMATCH_OBSERVECASE); i++)
474 		sorted_no_FULLMATCH_IGNORECASE [i + 1] = sorted_no_FULLMATCH_OBSERVECASE [i];
475 
476 	struct expectation sorted_no_PARTIALMATCH_OBSERVECASE [] = {
477 		{
478 			.name = "main",
479 			.file = "input.c",
480 			.pattern = "/^int main(int n)$/",
481 			.kind = "f",
482 			.scope_kind = NULL,
483 			.scope_name = NULL,
484 			.typeref = "typename:int",
485 			.fileScope = 0,
486 			.result = TagSuccess,
487 		},
488 		{
489 			.name = "m",
490 			.file = "input.c",
491 			.pattern = "/^int m;$/",
492 			.kind = "v",
493 			.scope_kind = NULL,
494 			.scope_name = NULL,
495 			.typeref = "typename:int",
496 			.fileScope = 0,
497 			.result = TagSuccess,
498 		},
499 	};
500 
501 	struct expectation sorted_no_PARTIALMATCH_IGNORECASE [COUNT(sorted_no_PARTIALMATCH_OBSERVECASE) + 1] = {
502 		[COUNT(sorted_no_PARTIALMATCH_OBSERVECASE)] = {
503 			.name = "M",
504 			.file = "input.c",
505 			.pattern = "/^int M (void) { return 0; }$/",
506 			.kind = "f",
507 			.scope_kind = NULL,
508 			.scope_name = NULL,
509 			.typeref = "typename:int",
510 			.fileScope = 0,
511 			.result = TagSuccess,
512 		},
513 	};
514 	for (int i = 0; i < COUNT(sorted_no_PARTIALMATCH_OBSERVECASE); i++)
515 		sorted_no_PARTIALMATCH_IGNORECASE [i] = sorted_no_PARTIALMATCH_OBSERVECASE [i];
516 
517 	if (check_finding (tags_sorted_no, "n", TAG_FULLMATCH|TAG_OBSERVECASE,
518 					   sorted_no_FULLMATCH_OBSERVECASE, COUNT(sorted_no_FULLMATCH_OBSERVECASE),
519 					   TESTX_NO_REMAIN) != 0)
520 		return 1;
521 
522 	if (check_finding (tags_sorted_no, "n", TAG_FULLMATCH|TAG_IGNORECASE,
523 					   sorted_no_FULLMATCH_IGNORECASE, COUNT(sorted_no_FULLMATCH_IGNORECASE),
524 					   TESTX_NO_REMAIN) != 0)
525 		return 1;
526 
527 	if (check_finding (tags_sorted_no, "m", TAG_PARTIALMATCH|TAG_OBSERVECASE,
528 					   sorted_no_PARTIALMATCH_OBSERVECASE, COUNT(sorted_no_PARTIALMATCH_OBSERVECASE),
529 					   TESTX_NO_REMAIN) != 0)
530 		return 1;
531 
532 	if (check_finding (tags_sorted_no, "m", TAG_PARTIALMATCH|TAG_IGNORECASE,
533 					   sorted_no_PARTIALMATCH_IGNORECASE, COUNT(sorted_no_PARTIALMATCH_IGNORECASE),
534 					   TESTX_NO_REMAIN) != 0)
535 		return 1;
536 
537 
538 	/*
539 	 * sorted=foldcase
540 	 */
541 	const char *tags_sorted_foldcase = "./duplicated-names--sorted-foldcase.tags";
542 	struct expectation sorted_foldcase_FULLMATCH_OBSERVECASE [COUNT(sorted_yes_FULLMATCH_OBSERVECASE)];
543 	for (int i = 0; i < COUNT(sorted_foldcase_FULLMATCH_OBSERVECASE); i++)
544 		sorted_foldcase_FULLMATCH_OBSERVECASE [i] =  sorted_yes_FULLMATCH_OBSERVECASE [i];
545 
546 	struct expectation sorted_foldcase_FULLMATCH_IGNORECASE [COUNT(sorted_foldcase_FULLMATCH_OBSERVECASE) + 1] = {
547 		[4] = {
548 			.name = "N",
549 			.file = "input.c",
550 			.pattern = "/^int N;$/",
551 			.kind = "v",
552 			.scope_kind = NULL,
553 			.scope_name = NULL,
554 			.typeref = "typename:int",
555 			.fileScope = 0,
556 			.result = TagSuccess,
557 		},
558 		[5] = sorted_foldcase_FULLMATCH_OBSERVECASE[4],
559 		[6] = sorted_foldcase_FULLMATCH_OBSERVECASE[5],
560 	};
561 	for (int i = 0; i < 4; i++)
562 		sorted_foldcase_FULLMATCH_IGNORECASE [i] = sorted_foldcase_FULLMATCH_OBSERVECASE [i];
563 
564 	struct expectation sorted_foldcase_PARTIALMATCH_OBSERVECASE [COUNT(sorted_yes_PARTIALMATCH_OBSERVECASE)];
565 	for (int i = 0; i < COUNT(sorted_foldcase_PARTIALMATCH_OBSERVECASE); i++)
566 		sorted_foldcase_PARTIALMATCH_OBSERVECASE [i] =  sorted_yes_PARTIALMATCH_OBSERVECASE [i];
567 
568 	struct expectation sorted_foldcase_PARTIALMATCH_IGNORECASE [COUNT(sorted_yes_PARTIALMATCH_IGNORECASE)];
569 	for (int i = 0; i < COUNT(sorted_foldcase_PARTIALMATCH_IGNORECASE); i++)
570 		sorted_foldcase_PARTIALMATCH_IGNORECASE [i] =  sorted_yes_PARTIALMATCH_IGNORECASE [i];
571 
572 
573 	if (check_finding (tags_sorted_foldcase, "n", TAG_FULLMATCH|TAG_OBSERVECASE,
574 					   sorted_foldcase_FULLMATCH_OBSERVECASE, COUNT(sorted_foldcase_FULLMATCH_OBSERVECASE),
575 					   TESTX_NO_REMAIN) != 0)
576 		return 1;
577 
578 	if (check_finding (tags_sorted_foldcase, "n", TAG_FULLMATCH|TAG_IGNORECASE,
579 					   sorted_foldcase_FULLMATCH_IGNORECASE, COUNT(sorted_foldcase_FULLMATCH_IGNORECASE),
580 					   TESTX_NO_REMAIN) != 0)
581 		return 1;
582 
583 	if (check_finding (tags_sorted_foldcase, "m", TAG_PARTIALMATCH|TAG_OBSERVECASE,
584 					   sorted_foldcase_PARTIALMATCH_OBSERVECASE, COUNT(sorted_foldcase_PARTIALMATCH_OBSERVECASE),
585 					   TESTX_NO_REMAIN) != 0)
586 		return 1;
587 
588 	if (check_finding (tags_sorted_foldcase, "m", TAG_PARTIALMATCH|TAG_IGNORECASE,
589 					   sorted_foldcase_PARTIALMATCH_IGNORECASE, COUNT(sorted_foldcase_PARTIALMATCH_IGNORECASE),
590 					   TESTX_NO_REMAIN) != 0)
591 		return 1;
592 
593 	/*
594 	 * Not found
595 	 */
596 	const char *tags_not_found = "./duplicated-names--sorted-yes.tags";
597 	struct expectation not_found_case = {
598 		.result = TagFailure,
599 		.err    = 0,
600 	};
601 	if (check_finding (tags_not_found, "noSuchItem", TAG_FULLMATCH|TAG_IGNORECASE,
602 					   &not_found_case, 1, TESTX_NO_REMAIN) != 0)
603 		return 1;
604 
605 	/*
606 	 * Broken line:
607 	 */
608 	const char *tags_broken_line_field = "./broken-line-field-in-middle.tags";
609 	struct expectation broken_line_case = {
610 		.result = TagFailure,
611 		.err    = TagErrnoUnexpectedLineno,
612 	};
613 	if (check_finding (tags_broken_line_field, "n", TAG_FULLMATCH|TAG_OBSERVECASE,
614 					   &broken_line_case, 1, TESTX_INVALID_ARG) != 0)
615 		return 1;
616 
617 	struct expectation broken_line_cases[] = {
618 		{
619 			.name = "N",
620 			.file = "duplicated-names.c",
621 			.pattern = "/^int N;$/",
622 			.kind = "v",
623 			.scope_kind = NULL,
624 			.scope_name = NULL,
625 			.typeref = "typename:int",
626 			.fileScope = 0,
627 			.result = TagSuccess,
628 		},
629 		{
630 			.result = TagFailure,
631 			.err    = TagErrnoUnexpectedLineno,
632 		},
633 	};
634 	if (check_finding (tags_broken_line_field, "n", TAG_FULLMATCH|TAG_IGNORECASE,
635 					   broken_line_cases, COUNT(broken_line_cases), TESTX_INVALID_ARG) != 0)
636 		return 1;
637 
638 	return 0;
639 }
640