xref: /Universal-ctags/libreadtags/tests/test-fix-large-tags.c (revision d5b81c4aa18f31534f9ed152bfb0988c340b28ff)
1 /*
2 *   Copyright (c) 2022, Masatake YAMATO
3 *
4 *   This source code is released into the public domain.
5 *
6 *   Testing the way to report "too large tags file".
7 */
8 
9 #include "readtags.h"
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <errno.h>
16 
17 #define	TAGS "./remove-me-after-testing.tags"
18 #define KEY "xdigitValue"
19 
20 static int
make_large_tags(const char * output)21 make_large_tags (const char *output)
22 {
23 	FILE *fp = fopen(output, "w");
24 	if (fp == NULL)
25 		return 1;
26 
27 	int r = 0;
28 	const char *ptags [] = {
29 		"!_TAG_FILE_FORMAT	2	/extended format; --format=1 will not append ;\" to lines/",
30 		"!_TAG_FILE_SORTED	1	/0=unsorted, 1=sorted, 2=foldcase/",
31 		"!_TAG_OUTPUT_EXCMD	mixed	/number, pattern, mixed, or combineV2/",
32 		"!_TAG_OUTPUT_FILESEP	slash	/slash or backslash/",
33 		"!_TAG_OUTPUT_MODE	u-ctags	/u-ctags or e-ctags/",
34 		"!_TAG_PATTERN_LENGTH_LIMIT	96	/0 for no limit/",
35 		"!_TAG_PROC_CWD	/home/jet/var/libreadtags-new/	//",
36 		"!_TAG_PROGRAM_AUTHOR	Universal Ctags Team	//",
37 		"!_TAG_PROGRAM_NAME	Universal Ctags	/Derived from Exuberant Ctags/",
38 		"!_TAG_PROGRAM_URL	https://ctags.io/	/official site/",
39 		"!_TAG_PROGRAM_VERSION	5.9.0	/966e51373/",
40 	};
41 
42 	for (unsigned int i = 0; i < sizeof (ptags) / sizeof (ptags[0]); i++)
43 	{
44 		if (fputs(ptags[i], fp) < 0)
45 		{
46 			r = 1;
47 			break;
48 		}
49 		if (fputc('\n', fp) == EOF)
50 		{
51 			r = 1;
52 			break;
53 		}
54 	}
55 
56 	const unsigned int count = 21474836;	/* $(( (2 ** 31) / 100)) */
57 	for (unsigned int i = 0; i < count; i++)
58 	{
59 		if (fputs("EmptyString", fp) < 0)
60 		{
61 			r = 1;
62 			break;
63 		}
64 
65 		if (fprintf(fp, "%u", i) < 1)
66 		{
67 			r = 1;
68 			break;
69 		}
70 		if (fputs("	readtags.c	/^static const char *const EmptyString", fp) < 0)
71 		{
72 			r = 1;
73 			break;
74 		}
75 
76 		if (fprintf(fp, "%u", i) < 1)
77 		{
78 			r = 1;
79 			break;
80 		}
81 		if (fputs(" = \"\";$/;\"	v	typeref:typename:const char * const	file:\n", fp) < 0)
82 		{
83 			r = 1;
84 			break;
85 		}
86 	}
87 
88 	if (r == 0)
89 	{
90 		if (fputs(KEY, fp) < 0)
91 			r = 1;
92 		else if (fputs("	readtags.c	/^static int xdigitValue (char digit)$/;\"	f	typeref:typename:int	file:\n", fp) < 0)
93 			r = 1;
94 	}
95 
96 	if (fclose (fp))
97 		r = 1;
98 
99 	return r;
100 }
101 
102 int
main(void)103 main (void)
104 {
105 	fprintf (stderr, "generating a large (> 2G) tags file (%s)...", TAGS);
106 
107 	errno = 0;
108 	int r = make_large_tags (TAGS);
109 	if (r)
110 	{
111 		fprintf(stderr, "unexpected result: %s%s%d\n",
112 				errno? strerror(errno): "",
113 				errno? ": ": "",
114 				r);
115 		return 99;
116 	}
117 	fprintf(stderr, "done\n");
118 
119 	fprintf(stderr, "opening tags file (%s)...", TAGS);
120 	tagFileInfo info;
121 	tagFile *t = tagsOpen (TAGS, &info);
122 	if ((info.status.opened == 0
123 		 && (
124 			 info.status.error_number == EFBIG
125 			 || info.status.error_number == TagErrnoFileMaybeTooBig)))
126 	{
127 		r = 1;
128 		fprintf(stderr, "failed with expected error: %d\n", info.status.error_number);
129 	}
130 	else if (t && info.status.opened)
131 		fprintf(stderr, "done\n");
132 	else
133 	{
134 		r = 1;
135 		fprintf (stderr, "unexpected result (t: %p, opened: %d, error_number: %d<%s>)\n",
136 				 t, info.status.opened, info.status.error_number,
137 				 (info.status.error_number >= 0)? strerror (info.status.error_number): "");
138 	}
139 
140 	if (t)
141 	{
142 		tagEntry e;
143 		fprintf (stderr, "finding \"%s\"...", KEY);
144 		if (tagsFind (t, &e, KEY, TAG_FULLMATCH) == TagSuccess)
145 			fprintf (stderr, "found as expected\n");
146 		else
147 		{
148 			r = 1;
149 			fprintf (stderr, "not found unexpectedly\n");
150 		}
151 		tagsClose (t);
152 	}
153 
154 	remove(TAGS);
155 	return r;
156 }
157