tests: handle locations in a more generic way.
[bison.git] / tests / torture.at
0 / 536 (  0%)
CommitLineData
1# Torturing Bison. -*- Autotest -*-
2
3# Copyright (C) 2001-2002, 2004-2007, 2009-2012 Free Software
4# Foundation, Inc.
5
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19AT_BANNER([[Torture Tests.]])
20
21
22# AT_INCREASE_DATA_SIZE(SIZE)
23# ---------------------------
24# Try to increase the data size to SIZE KiB if possible.
25m4_define([AT_INCREASE_DATA_SIZE],
26[data_limit=`(ulimit -S -d) 2>/dev/null`
27case $data_limit in
28[[0-9]]*)
29 if test "$data_limit" -lt $1; then
30 AT_CHECK([ulimit -S -d $1 || exit 77])
31 ulimit -S -d $1
32 fi
33esac])
34
35
36## ------------------------------------- ##
37## Creating a large artificial grammar. ##
38## ------------------------------------- ##
39
40# AT_DATA_TRIANGULAR_GRAMMAR(FILE-NAME, SIZE)
41# -------------------------------------------
42# Create FILE-NAME, containing a self checking parser for a huge
43# triangular grammar.
44m4_define([AT_DATA_TRIANGULAR_GRAMMAR],
45[AT_BISON_OPTION_PUSHDEFS
46AT_DATA([[gengram.pl]],
47[[#! /usr/bin/perl -w
48
49use strict;
50my $max = $ARGV[0] || 10;
51
52print <<EOF;
53]AT_DATA_GRAMMAR_PROLOGUE[
54%error-verbose
55%debug
56%{
57#include <stdio.h>
58#include <stdlib.h>
59#define MAX $max
60]AT_YYLEX_DECLARE[
61]AT_YYERROR_DECLARE[
62%}
63%union
64{
65 int val;
66};
67
68%token END "end"
69%type <val> exp input
70EOF
71
72for my $size (1 .. $max)
73 {
74 print "%token t$size $size \"$size\"\n";
75 };
76
77print <<EOF;
78%%
79input:
80 exp { if (\@S|@1 != 0) abort (); \$\$ = \@S|@1; }
81| input exp { if (\@S|@2 != \@S|@1 + 1) abort (); \$\$ = \@S|@2; }
82;
83
84exp:
85 END
86 { \$\$ = 0; }
87EOF
88
89for my $size (1 .. $max)
90 {
91 use Text::Wrap;
92 print wrap ("| ", " ",
93 (map { "\"$_\"" } (1 .. $size)),
94 " END \n"),
95 " { \$\$ = $size; }\n";
96 };
97print ";\n";
98
99print <<\EOF;
100%%
101]AT_YYERROR_DEFINE[
102static int
103yylex (void)
104{
105 static int inner = 1;
106 static int outer = 0;
107 if (outer > MAX)
108 return 0;
109 else if (inner > outer)
110 {
111 inner = 1;
112 ++outer;
113 return END;
114 }
115 return inner++;
116}
117int
118main (void)
119{
120 yydebug = !!getenv ("YYDEBUG");
121 return yyparse ();
122}
123EOF
124]])
125AT_BISON_OPTION_POPDEFS
126
127AT_CHECK([perl -w ./gengram.pl $2 || exit 77], 0, [stdout])
128mv stdout $1
129])
130
131
132## -------------- ##
133## Big triangle. ##
134## -------------- ##
135
136AT_SETUP([Big triangle])
137
138# I have been able to go up to 2000 on my machine.
139# I tried 3000, a 29Mb grammar file, but then my system killed bison.
140# With 500 and the new parser, which consume far too much memory,
141# it gets killed too. Of course the parser is to be cleaned.
142AT_DATA_TRIANGULAR_GRAMMAR([input.y], [200])
143AT_BISON_CHECK_NO_XML([-v -o input.c input.y])
144AT_COMPILE([input])
145AT_PARSER_CHECK([./input])
146
147AT_CLEANUP
148
149
150
151# AT_DATA_HORIZONTAL_GRAMMAR(FILE-NAME, SIZE)
152# -------------------------------------------
153# Create FILE-NAME, containing a self checking parser for a huge
154# horizontal grammar.
155m4_define([AT_DATA_HORIZONTAL_GRAMMAR],
156[AT_BISON_OPTION_PUSHDEFS
157AT_DATA([[gengram.pl]],
158[[#! /usr/bin/perl -w
159
160use strict;
161my $max = $ARGV[0] || 10;
162
163print <<EOF;
164]AT_DATA_GRAMMAR_PROLOGUE[
165%error-verbose
166%debug
167%{
168#include <stdio.h>
169#include <stdlib.h>
170#define MAX $max
171]AT_YYLEX_DECLARE[
172]AT_YYERROR_DECLARE[
173%}
174
175%token
176EOF
177for my $size (1 .. $max)
178 {
179 print " t$size $size \"$size\"\n";
180 };
181
182print <<EOF;
183
184%%
185EOF
186
187use Text::Wrap;
188print
189 wrap ("exp: ", " ",
190 (map { "\"$_\"" } (1 .. $max)), ";"),
191 "\n";
192
193print <<\EOF;
194%%
195]AT_YYERROR_DEFINE[
196static int
197yylex (void)
198{
199 static int counter = 1;
200 if (counter <= MAX)
201 return counter++;
202 if (counter++ != MAX + 1)
203 abort ();
204 return 0;
205}
206
207int
208main (void)
209{
210 yydebug = !!getenv ("YYDEBUG");
211 return yyparse ();
212}
213EOF
214]])
215
216AT_CHECK([perl -w ./gengram.pl $2 || exit 77], 0, [stdout])
217mv stdout $1
218AT_BISON_OPTION_POPDEFS
219])
220
221
222## ---------------- ##
223## Big horizontal. ##
224## ---------------- ##
225
226AT_SETUP([Big horizontal])
227
228# I have been able to go up to 10000 on my machine, but I had to
229# increase the maximum stack size (* 100). It gave:
230#
231# input.y 263k
232# input.tab.c 1.3M
233# input 453k
234#
235# gengram.pl 10000 0.70s user 0.01s sys 99% cpu 0.711 total
236# bison input.y 730.56s user 0.53s sys 99% cpu 12:12.34 total
237# gcc -Wall input.tab.c -o input 5.81s user 0.20s sys 100% cpu 6.01 total
238# ./input 0.00s user 0.01s sys 108% cpu 0.01 total
239#
240AT_DATA_HORIZONTAL_GRAMMAR([input.y], [1000])
241
242# GNU m4 requires about 70 MiB for this test on a 32-bit host.
243# Ask for 200 MiB, which should be plenty even on a 64-bit host.
244AT_INCREASE_DATA_SIZE(204000)
245
246AT_BISON_CHECK_NO_XML([-v -o input.c input.y])
247AT_COMPILE([input])
248AT_PARSER_CHECK([./input])
249
250AT_CLEANUP
251
252
253
254# AT_DATA_LOOKAHEAD_TOKENS_GRAMMAR(FILE-NAME, SIZE)
255# --------------------------------------------------
256# Create FILE-NAME, containing a self checking parser for a grammar
257# requiring SIZE lookahead tokens.
258m4_define([AT_DATA_LOOKAHEAD_TOKENS_GRAMMAR],
259[AT_BISON_OPTION_PUSHDEFS
260AT_DATA([[gengram.pl]],
261[[#! /usr/bin/perl -w
262
263use strict;
264use Text::Wrap;
265my $max = $ARGV[0] || 10;
266
267print <<EOF;
268%error-verbose
269%debug
270%{
271# include <stdio.h>
272# include <stdlib.h>
273# include <assert.h>
274# define MAX $max
275]AT_YYLEX_DECLARE[
276]AT_YYERROR_DECLARE[
277%}
278%union
279{
280 int val;
281};
282
283%type <val> input exp
284%token token
285EOF
286
287print
288 wrap ("%type <val> ",
289 " ",
290 map { "n$_" } (1 .. $max)),
291 "\n";
292
293print "%token\n";
294for my $count (1 .. $max)
295 {
296 print " t$count $count \"$count\"\n";
297 };
298
299print <<EOF;
300%%
301input:
302 exp { assert (\@S|@1 == 1); \$\$ = \@S|@1; }
303| input exp { assert (\@S|@2 == \@S|@1 + 1); \$\$ = \@S|@2; }
304;
305
306exp:
307 n1 "1" { assert (\@S|@1 == 1); \@S|@\@S|@ = \@S|@1; }
308EOF
309
310for my $count (2 .. $max)
311 {
312 print "| n$count \"$count\" { assert (\@S|@1 == $count); \@S|@\@S|@ = \@S|@1; }\n";
313 };
314print ";\n";
315
316for my $count (1 .. $max)
317 {
318 print "n$count: token { \$\$ = $count; };\n";
319 };
320
321print <<\EOF;
322%%
323]AT_YYERROR_DEFINE[
324static int
325yylex (void)
326{
327 static int return_token = 1;
328 static int counter = 1;
329 if (counter > MAX)
330 {
331 if (counter++ != MAX + 1)
332 abort ();
333 return 0;
334 }
335 if (return_token)
336 {
337 return_token = 0;
338 return token;
339 }
340 return_token = 1;
341 return counter++;
342}
343
344int
345main (void)
346{
347 yydebug = !!getenv ("YYDEBUG");
348 return yyparse ();
349}
350EOF
351]])
352
353AT_CHECK([perl -w ./gengram.pl $2 || exit 77], 0, [stdout])
354mv stdout $1
355AT_BISON_OPTION_POPDEFS
356])
357
358
359## ------------------------ ##
360## Many lookahead tokens. ##
361## ------------------------ ##
362
363AT_SETUP([Many lookahead tokens])
364
365AT_DATA_LOOKAHEAD_TOKENS_GRAMMAR([input.y], [1000])
366
367# GNU m4 requires about 70 MiB for this test on a 32-bit host.
368# Ask for 200 MiB, which should be plenty even on a 64-bit host.
369AT_INCREASE_DATA_SIZE(204000)
370
371AT_BISON_CHECK([-v -o input.c input.y])
372AT_COMPILE([input])
373AT_PARSER_CHECK([./input])
374
375AT_CLEANUP
376
377
378
379# AT_DATA_STACK_TORTURE(C-PROLOGUE, [BISON-DECLS])
380# ------------------------------------------------
381# A parser specialized in torturing the stack size.
382m4_define([AT_DATA_STACK_TORTURE],
383[AT_BISON_OPTION_PUSHDEFS([$2])
384# A grammar of parens growing the stack thanks to right recursion.
385# exp:
386AT_DATA([input.y],
387[[%{
388#include <errno.h>
389#include <limits.h>
390#include <stdio.h>
391#include <stdlib.h>
392]$1[
393 ]AT_YYLEX_DECLARE[
394 ]AT_YYERROR_DECLARE[
395%}
396]$2[
397%error-verbose
398%debug
399%token WAIT_FOR_EOF
400%%
401exp: WAIT_FOR_EOF exp | ;
402%%
403]AT_YYERROR_DEFINE[
404static int
405yylex (void)
406{
407 if (yylval < 0)
408 abort ();
409 if (yylval--)
410 return WAIT_FOR_EOF;
411 else
412 return EOF;
413}
414
415int
416main (int argc, const char **argv)
417{
418 char *endp;
419 YYSTYPE yylval_init;
420 if (argc != 2)
421 abort ();
422 yylval_init = strtol (argv[1], &endp, 10);
423 if (! (argv[1] != endp
424 && 0 <= yylval_init && yylval_init <= INT_MAX
425 && errno != ERANGE))
426 abort ();
427 yydebug = 1;
428 {
429 int count;
430 int status;
431]m4_bmatch([$2], [%push-],
432[[ yypstate *ps = yypstate_new ();
433]])[ for (count = 0; count < 2; ++count)
434 {
435 int new_status;
436 yylval = yylval_init;
437]m4_bmatch([$2], [%push-],
438[[ new_status = yypull_parse (ps);
439]],
440[[ new_status = yyparse ();
441]])[ if (count > 0 && new_status != status)
442 abort ();
443 status = new_status;
444 }
445]m4_bmatch([$2], [%push-],
446[[ yypstate_delete (ps);
447]])[ return status;
448 }
449}
450]])
451AT_BISON_OPTION_POPDEFS([$2])
452AT_BISON_CHECK([-o input.c input.y])
453AT_COMPILE([input])
454])
455
456
457## -------------------------------------- ##
458## Exploding the Stack Size with Alloca. ##
459## -------------------------------------- ##
460
461AT_SETUP([Exploding the Stack Size with Alloca])
462
463m4_pushdef([AT_USE_ALLOCA], [[
464#if (defined __GNUC__ || defined __BUILTIN_VA_ARG_INCR \
465 || defined _AIX || defined _MSC_VER || defined _ALLOCA_H)
466# define YYSTACK_USE_ALLOCA 1
467#endif
468]])
469
470AT_DATA_STACK_TORTURE([AT_USE_ALLOCA])
471
472# Below the limit of 200.
473AT_PARSER_CHECK([./input 20], 0, [], [ignore],
474 [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
475# Two enlargements: 2 * 2 * 200.
476AT_PARSER_CHECK([./input 900], 0, [], [ignore],
477 [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
478# Fails: beyond the limit of 10,000 (which we don't reach anyway since we
479# multiply by two starting at 200 => 5120 is the last possible).
480AT_PARSER_CHECK([./input 10000], 2, [], [ignore],
481 [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
482
483# The push parser can't use alloca since the stacks can't be locals. This test
484# just helps guarantee we don't let the YYSTACK_USE_ALLOCA feature affect
485# push parsers.
486AT_DATA_STACK_TORTURE([AT_USE_ALLOCA],
487[[%define api.push-pull both
488]])
489AT_PARSER_CHECK([./input 20], 0, [], [ignore],
490 [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
491AT_PARSER_CHECK([./input 900], 0, [], [ignore],
492 [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
493AT_PARSER_CHECK([./input 10000], 2, [], [ignore],
494 [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
495
496m4_popdef([AT_USE_ALLOCA])
497
498AT_CLEANUP
499
500
501
502
503## -------------------------------------- ##
504## Exploding the Stack Size with Malloc. ##
505## -------------------------------------- ##
506
507AT_SETUP([Exploding the Stack Size with Malloc])
508
509m4_pushdef([AT_USE_ALLOCA], [[#define YYSTACK_USE_ALLOCA 0]])
510
511AT_DATA_STACK_TORTURE([AT_USE_ALLOCA])
512
513# Below the limit of 200.
514AT_PARSER_CHECK([./input 20], 0, [], [ignore],
515 [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
516# Two enlargements: 2 * 2 * 200.
517AT_PARSER_CHECK([./input 900], 0, [], [ignore],
518 [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
519# Fails: beyond the limit of 10,000 (which we don't reach anyway since we
520# multiply by two starting at 200 => 5120 is the possible).
521AT_PARSER_CHECK([./input 10000], 2, [], [ignore],
522 [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
523
524AT_DATA_STACK_TORTURE([AT_USE_ALLOCA],
525[[%define api.push-pull both
526]])
527AT_PARSER_CHECK([./input 20], 0, [], [ignore],
528 [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
529AT_PARSER_CHECK([./input 900], 0, [], [ignore],
530 [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
531AT_PARSER_CHECK([./input 10000], 2, [], [ignore],
532 [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
533
534m4_popdef([AT_USE_ALLOCA])
535
536AT_CLEANUP