| Index: bison/src/bison/2.4.1/bison-2.4.1-src/tests/torture.at
|
| ===================================================================
|
| --- bison/src/bison/2.4.1/bison-2.4.1-src/tests/torture.at (revision 0)
|
| +++ bison/src/bison/2.4.1/bison-2.4.1-src/tests/torture.at (revision 0)
|
| @@ -0,0 +1,548 @@
|
| +# Torturing Bison. -*- Autotest -*-
|
| +# Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007 Free Software Foundation,
|
| +# Inc.
|
| +
|
| +# This program is free software: you can redistribute it and/or modify
|
| +# it under the terms of the GNU General Public License as published by
|
| +# the Free Software Foundation, either version 3 of the License, or
|
| +# (at your option) any later version.
|
| +#
|
| +# This program is distributed in the hope that it will be useful,
|
| +# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| +# GNU General Public License for more details.
|
| +#
|
| +# You should have received a copy of the GNU General Public License
|
| +# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
| +
|
| +AT_BANNER([[Torture Tests.]])
|
| +
|
| +
|
| +# AT_INCREASE_DATA_SIZE(SIZE)
|
| +# ---------------------------
|
| +# Try to increase the data size to SIZE KiB if possible.
|
| +m4_define([AT_INCREASE_DATA_SIZE],
|
| +[data_limit=`(ulimit -S -d) 2>/dev/null`
|
| +case $data_limit in
|
| +[[0-9]]*)
|
| + if test "$data_limit" -lt $1; then
|
| + AT_CHECK([ulimit -S -d $1 || exit 77])
|
| + ulimit -S -d $1
|
| + fi
|
| +esac])
|
| +
|
| +
|
| +## ------------------------------------- ##
|
| +## Creating a large artificial grammar. ##
|
| +## ------------------------------------- ##
|
| +
|
| +# AT_DATA_TRIANGULAR_GRAMMAR(FILE-NAME, SIZE)
|
| +# -------------------------------------------
|
| +# Create FILE-NAME, containing a self checking parser for a huge
|
| +# triangular grammar.
|
| +m4_define([AT_DATA_TRIANGULAR_GRAMMAR],
|
| +[AT_DATA([[gengram.pl]],
|
| +[[#! /usr/bin/perl -w
|
| +
|
| +use strict;
|
| +my $max = $ARGV[0] || 10;
|
| +
|
| +print <<EOF;
|
| +]AT_DATA_GRAMMAR_PROLOGUE[
|
| +%error-verbose
|
| +%debug
|
| +%{
|
| +#include <stdio.h>
|
| +#include <stdlib.h>
|
| +
|
| +static int yylex (void);
|
| +static void yyerror (const char *msg);
|
| +%}
|
| +%union
|
| +{
|
| + int val;
|
| +};
|
| +
|
| +%token END "end"
|
| +%type <val> exp input
|
| +EOF
|
| +
|
| +for my $size (1 .. $max)
|
| + {
|
| + print "%token t$size $size \"$size\"\n";
|
| + };
|
| +
|
| +print <<EOF;
|
| +%%
|
| +input:
|
| + exp { if (\@S|@1 != 0) abort (); \$\$ = \@S|@1; }
|
| +| input exp { if (\@S|@2 != \@S|@1 + 1) abort (); \$\$ = \@S|@2; }
|
| +;
|
| +
|
| +exp:
|
| + END
|
| + { \$\$ = 0; }
|
| +EOF
|
| +
|
| +for my $size (1 .. $max)
|
| + {
|
| + use Text::Wrap;
|
| + print wrap ("| ", " ",
|
| + (map { "\"$_\"" } (1 .. $size)),
|
| + " END \n"),
|
| + " { \$\$ = $size; }\n";
|
| + };
|
| +print ";\n";
|
| +
|
| +print <<EOF;
|
| +%%
|
| +static int
|
| +yylex (void)
|
| +{
|
| + static int inner = 1;
|
| + static int outer = 0;
|
| + if (outer > $max)
|
| + return 0;
|
| + else if (inner > outer)
|
| + {
|
| + inner = 1;
|
| + ++outer;
|
| + return END;
|
| + }
|
| + return inner++;
|
| +}
|
| +
|
| +static void
|
| +yyerror (const char *msg)
|
| +{
|
| + fprintf (stderr, "%s\\n", msg);
|
| +}
|
| +
|
| +int
|
| +main (void)
|
| +{
|
| + yydebug = !!getenv ("YYDEBUG");
|
| + return yyparse ();
|
| +}
|
| +EOF
|
| +]])
|
| +
|
| +AT_CHECK([perl -w ./gengram.pl $2 || exit 77], 0, [stdout])
|
| +mv stdout $1
|
| +])
|
| +
|
| +
|
| +## -------------- ##
|
| +## Big triangle. ##
|
| +## -------------- ##
|
| +
|
| +AT_SETUP([Big triangle])
|
| +
|
| +# I have been able to go up to 2000 on my machine.
|
| +# I tried 3000, a 29Mb grammar file, but then my system killed bison.
|
| +# With 500 and the new parser, which consume far too much memory,
|
| +# it gets killed too. Of course the parser is to be cleaned.
|
| +AT_DATA_TRIANGULAR_GRAMMAR([input.y], [200])
|
| +AT_BISON_CHECK_NO_XML([-v -o input.c input.y])
|
| +AT_COMPILE([input])
|
| +AT_PARSER_CHECK([./input])
|
| +
|
| +AT_CLEANUP
|
| +
|
| +
|
| +
|
| +# AT_DATA_HORIZONTAL_GRAMMAR(FILE-NAME, SIZE)
|
| +# -------------------------------------------
|
| +# Create FILE-NAME, containing a self checking parser for a huge
|
| +# horizontal grammar.
|
| +m4_define([AT_DATA_HORIZONTAL_GRAMMAR],
|
| +[AT_DATA([[gengram.pl]],
|
| +[[#! /usr/bin/perl -w
|
| +
|
| +use strict;
|
| +my $max = $ARGV[0] || 10;
|
| +
|
| +print <<EOF;
|
| +]AT_DATA_GRAMMAR_PROLOGUE[
|
| +%error-verbose
|
| +%debug
|
| +%{
|
| +#include <stdio.h>
|
| +#include <stdlib.h>
|
| +
|
| +static int yylex (void);
|
| +static void yyerror (const char *msg);
|
| +%}
|
| +
|
| +%token
|
| +EOF
|
| +for my $size (1 .. $max)
|
| + {
|
| + print " t$size $size \"$size\"\n";
|
| + };
|
| +
|
| +print <<EOF;
|
| +
|
| +%%
|
| +EOF
|
| +
|
| +use Text::Wrap;
|
| +print
|
| + wrap ("exp: ", " ",
|
| + (map { "\"$_\"" } (1 .. $max)), ";"),
|
| + "\n";
|
| +
|
| +print <<EOF;
|
| +%%
|
| +static int
|
| +yylex (void)
|
| +{
|
| + static int counter = 1;
|
| + if (counter <= $max)
|
| + return counter++;
|
| + if (counter++ != $max + 1)
|
| + abort ();
|
| + return 0;
|
| +}
|
| +
|
| +static void
|
| +yyerror (const char *msg)
|
| +{
|
| + fprintf (stderr, "%s\\n", msg);
|
| +}
|
| +
|
| +int
|
| +main (void)
|
| +{
|
| + yydebug = !!getenv ("YYDEBUG");
|
| + return yyparse ();
|
| +}
|
| +EOF
|
| +]])
|
| +
|
| +AT_CHECK([perl -w ./gengram.pl $2 || exit 77], 0, [stdout])
|
| +mv stdout $1
|
| +])
|
| +
|
| +
|
| +## ---------------- ##
|
| +## Big horizontal. ##
|
| +## ---------------- ##
|
| +
|
| +AT_SETUP([Big horizontal])
|
| +
|
| +# I have been able to go up to 10000 on my machine, but I had to
|
| +# increase the maximum stack size (* 100). It gave:
|
| +#
|
| +# input.y 263k
|
| +# input.tab.c 1.3M
|
| +# input 453k
|
| +#
|
| +# gengram.pl 10000 0.70s user 0.01s sys 99% cpu 0.711 total
|
| +# bison input.y 730.56s user 0.53s sys 99% cpu 12:12.34 total
|
| +# gcc -Wall input.tab.c -o input 5.81s user 0.20s sys 100% cpu 6.01 total
|
| +# ./input 0.00s user 0.01s sys 108% cpu 0.01 total
|
| +#
|
| +AT_DATA_HORIZONTAL_GRAMMAR([input.y], [1000])
|
| +
|
| +# GNU m4 requires about 70 MiB for this test on a 32-bit host.
|
| +# Ask for 200 MiB, which should be plenty even on a 64-bit host.
|
| +AT_INCREASE_DATA_SIZE(204000)
|
| +
|
| +AT_BISON_CHECK_NO_XML([-v -o input.c input.y])
|
| +AT_COMPILE([input])
|
| +AT_PARSER_CHECK([./input])
|
| +
|
| +AT_CLEANUP
|
| +
|
| +
|
| +
|
| +# AT_DATA_LOOKAHEAD_TOKENS_GRAMMAR(FILE-NAME, SIZE)
|
| +# --------------------------------------------------
|
| +# Create FILE-NAME, containing a self checking parser for a grammar
|
| +# requiring SIZE lookahead tokens.
|
| +m4_define([AT_DATA_LOOKAHEAD_TOKENS_GRAMMAR],
|
| +[AT_DATA([[gengram.pl]],
|
| +[[#! /usr/bin/perl -w
|
| +
|
| +use strict;
|
| +use Text::Wrap;
|
| +my $max = $ARGV[0] || 10;
|
| +
|
| +print <<EOF;
|
| +%error-verbose
|
| +%debug
|
| +%{
|
| +# include <stdio.h>
|
| +# include <stdlib.h>
|
| +# include <assert.h>
|
| +
|
| +static int yylex (void);
|
| +static void yyerror (const char *msg);
|
| +%}
|
| +%union
|
| +{
|
| + int val;
|
| +};
|
| +
|
| +%type <val> input exp
|
| +%token token
|
| +EOF
|
| +
|
| +print
|
| + wrap ("%type <val> ",
|
| + " ",
|
| + map { "n$_" } (1 .. $max)),
|
| + "\n";
|
| +
|
| +print "%token\n";
|
| +for my $count (1 .. $max)
|
| + {
|
| + print " t$count $count \"$count\"\n";
|
| + };
|
| +
|
| +print <<EOF;
|
| +%%
|
| +input:
|
| + exp { assert (\@S|@1 == 1); \$\$ = \@S|@1; }
|
| +| input exp { assert (\@S|@2 == \@S|@1 + 1); \$\$ = \@S|@2; }
|
| +;
|
| +
|
| +exp:
|
| + n1 "1" { assert (\@S|@1 == 1); \@S|@\@S|@ = \@S|@1; }
|
| +EOF
|
| +
|
| +for my $count (2 .. $max)
|
| + {
|
| + print "| n$count \"$count\" { assert (\@S|@1 == $count); \@S|@\@S|@ = \@S|@1; }\n";
|
| + };
|
| +print ";\n";
|
| +
|
| +for my $count (1 .. $max)
|
| + {
|
| + print "n$count: token { \$\$ = $count; };\n";
|
| + };
|
| +
|
| +print <<EOF;
|
| +%%
|
| +static int
|
| +yylex (void)
|
| +{
|
| + static int return_token = 1;
|
| + static int counter = 1;
|
| + if (counter > $max)
|
| + {
|
| + if (counter++ != $max + 1)
|
| + abort ();
|
| + return 0;
|
| + }
|
| + if (return_token)
|
| + {
|
| + return_token = 0;
|
| + return token;
|
| + }
|
| + return_token = 1;
|
| + return counter++;
|
| +}
|
| +
|
| +static void
|
| +yyerror (const char *msg)
|
| +{
|
| + fprintf (stderr, "%s\\n", msg);
|
| +}
|
| +
|
| +int
|
| +main (void)
|
| +{
|
| + yydebug = !!getenv ("YYDEBUG");
|
| + return yyparse ();
|
| +}
|
| +EOF
|
| +]])
|
| +
|
| +AT_CHECK([perl -w ./gengram.pl $2 || exit 77], 0, [stdout])
|
| +mv stdout $1
|
| +])
|
| +
|
| +
|
| +## ------------------------ ##
|
| +## Many lookahead tokens. ##
|
| +## ------------------------ ##
|
| +
|
| +AT_SETUP([Many lookahead tokens])
|
| +
|
| +AT_DATA_LOOKAHEAD_TOKENS_GRAMMAR([input.y], [1000])
|
| +
|
| +# GNU m4 requires about 70 MiB for this test on a 32-bit host.
|
| +# Ask for 200 MiB, which should be plenty even on a 64-bit host.
|
| +AT_INCREASE_DATA_SIZE(204000)
|
| +
|
| +AT_BISON_CHECK([-v -o input.c input.y])
|
| +AT_COMPILE([input])
|
| +AT_PARSER_CHECK([./input])
|
| +
|
| +AT_CLEANUP
|
| +
|
| +
|
| +
|
| +# AT_DATA_STACK_TORTURE(C-PROLOGUE, [BISON-DECLS])
|
| +# ------------------------------------------------
|
| +# A parser specialized in torturing the stack size.
|
| +m4_define([AT_DATA_STACK_TORTURE],
|
| +[# A grammar of parens growing the stack thanks to right recursion.
|
| +# exp:
|
| +AT_DATA([input.y],
|
| +[[%{
|
| +#include <errno.h>
|
| +#include <limits.h>
|
| +#include <stdio.h>
|
| +#include <stdlib.h>
|
| +]$1[
|
| + static int yylex (void);
|
| + static void yyerror (const char *msg);
|
| +%}
|
| +]$2[
|
| +%error-verbose
|
| +%debug
|
| +%token WAIT_FOR_EOF
|
| +%%
|
| +exp: WAIT_FOR_EOF exp | ;
|
| +%%
|
| +static void
|
| +yyerror (const char *msg)
|
| +{
|
| + fprintf (stderr, "%s\n", msg);
|
| +}
|
| +
|
| +static int
|
| +yylex (void)
|
| +{
|
| + if (yylval < 0)
|
| + abort ();
|
| + if (yylval--)
|
| + return WAIT_FOR_EOF;
|
| + else
|
| + return EOF;
|
| +}
|
| +
|
| +int
|
| +main (int argc, const char **argv)
|
| +{
|
| + char *endp;
|
| + YYSTYPE yylval_init;
|
| + if (argc != 2)
|
| + abort ();
|
| + yylval_init = strtol (argv[1], &endp, 10);
|
| + if (! (argv[1] != endp
|
| + && 0 <= yylval_init && yylval_init <= INT_MAX
|
| + && errno != ERANGE))
|
| + abort ();
|
| + yydebug = 1;
|
| + {
|
| + int count;
|
| + int status;
|
| +]m4_bmatch([$2], [%push-],
|
| +[[ yypstate *ps = yypstate_new ();
|
| +]])[ for (count = 0; count < 2; ++count)
|
| + {
|
| + int new_status;
|
| + yylval = yylval_init;
|
| +]m4_bmatch([$2], [%push-],
|
| +[[ new_status = yypull_parse (ps);
|
| +]],
|
| +[[ new_status = yyparse ();
|
| +]])[ if (count > 0 && new_status != status)
|
| + abort ();
|
| + status = new_status;
|
| + }
|
| +]m4_bmatch([$2], [%push-],
|
| +[[ yypstate_delete (ps);
|
| +]])[ return status;
|
| + }
|
| +}
|
| +]])
|
| +AT_BISON_CHECK([-o input.c input.y])
|
| +AT_COMPILE([input])
|
| +])
|
| +
|
| +
|
| +## -------------------------------------- ##
|
| +## Exploding the Stack Size with Alloca. ##
|
| +## -------------------------------------- ##
|
| +
|
| +AT_SETUP([Exploding the Stack Size with Alloca])
|
| +
|
| +m4_pushdef([AT_USE_ALLOCA], [[
|
| +#if (defined __GNUC__ || defined __BUILTIN_VA_ARG_INCR \
|
| + || defined _AIX || defined _MSC_VER || defined _ALLOCA_H)
|
| +# define YYSTACK_USE_ALLOCA 1
|
| +#endif
|
| +]])
|
| +
|
| +AT_DATA_STACK_TORTURE([AT_USE_ALLOCA])
|
| +
|
| +# Below the limit of 200.
|
| +AT_PARSER_CHECK([./input 20], 0, [], [ignore],
|
| + [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
|
| +# Two enlargements: 2 * 2 * 200.
|
| +AT_PARSER_CHECK([./input 900], 0, [], [ignore],
|
| + [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
|
| +# Fails: beyond the limit of 10,000 (which we don't reach anyway since we
|
| +# multiply by two starting at 200 => 5120 is the last possible).
|
| +AT_PARSER_CHECK([./input 10000], 2, [], [ignore],
|
| + [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
|
| +
|
| +# The push parser can't use alloca since the stacks can't be locals. This test
|
| +# just helps guarantee we don't let the YYSTACK_USE_ALLOCA feature affect
|
| +# push parsers.
|
| +AT_DATA_STACK_TORTURE([AT_USE_ALLOCA],
|
| +[[%define api.push_pull "both"
|
| +]])
|
| +AT_PARSER_CHECK([./input 20], 0, [], [ignore],
|
| + [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
|
| +AT_PARSER_CHECK([./input 900], 0, [], [ignore],
|
| + [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
|
| +AT_PARSER_CHECK([./input 10000], 2, [], [ignore],
|
| + [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
|
| +
|
| +m4_popdef([AT_USE_ALLOCA])
|
| +
|
| +AT_CLEANUP
|
| +
|
| +
|
| +
|
| +
|
| +## -------------------------------------- ##
|
| +## Exploding the Stack Size with Malloc. ##
|
| +## -------------------------------------- ##
|
| +
|
| +AT_SETUP([Exploding the Stack Size with Malloc])
|
| +
|
| +m4_pushdef([AT_USE_ALLOCA], [[#define YYSTACK_USE_ALLOCA 0]])
|
| +
|
| +AT_DATA_STACK_TORTURE([AT_USE_ALLOCA])
|
| +
|
| +# Below the limit of 200.
|
| +AT_PARSER_CHECK([./input 20], 0, [], [ignore],
|
| + [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
|
| +# Two enlargements: 2 * 2 * 200.
|
| +AT_PARSER_CHECK([./input 900], 0, [], [ignore],
|
| + [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
|
| +# Fails: beyond the limit of 10,000 (which we don't reach anyway since we
|
| +# multiply by two starting at 200 => 5120 is the possible).
|
| +AT_PARSER_CHECK([./input 10000], 2, [], [ignore],
|
| + [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
|
| +
|
| +AT_DATA_STACK_TORTURE([AT_USE_ALLOCA],
|
| +[[%define api.push_pull "both"
|
| +]])
|
| +AT_PARSER_CHECK([./input 20], 0, [], [ignore],
|
| + [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
|
| +AT_PARSER_CHECK([./input 900], 0, [], [ignore],
|
| + [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
|
| +AT_PARSER_CHECK([./input 10000], 2, [], [ignore],
|
| + [[VALGRIND_OPTS="$VALGRIND_OPTS --log-fd=1"]])
|
| +
|
| +m4_popdef([AT_USE_ALLOCA])
|
| +
|
| +AT_CLEANUP
|
|
|