1 # Hand crafted tests for GNU M4. -*- Autotest -*-
2 # Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation,
5 # This file is part of GNU M4.
7 # GNU M4 is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
12 # GNU M4 is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 # AT_TEST_FREEZE([title], [text1], [text2])
21 # -----------------------------------------
22 # Create a test TITLE, which checks that freezing TEXT1, then reloading
23 # it with TEXT2, produces the same results as running TEXT1 and TEXT2 in
25 m4_define([AT_TEST_FREEZE],
29 AT_DATA([frozen.m4], [$2])
30 AT_DATA([unfrozen.m4], [$3])
32 # First generate the `expout' output by running over the sources before
34 AT_CHECK_M4([frozen.m4 unfrozen.m4], [0], [stdout-nolog], [stderr])
39 # Now freeze the first source file.
40 AT_CHECK_M4([-F frozen.m4f frozen.m4], [0], [stdout-nolog])
44 # Now rerun the original sequence, but using the frozen file.
45 AT_CHECK_M4([-R frozen.m4f unfrozen.m4],
46 [0], [stdout-nolog], [experr], [], [ ])
48 AT_CHECK([cat out1 stdout], [0], [expout])
54 AT_BANNER([Freezing state.])
56 ## ---------------- ##
57 ## freezing failure ##
58 ## ---------------- ##
60 AT_SETUP([freezing failure])
63 AT_CHECK_M4([-F /none/such], [1], [],
64 [[m4: cannot open '/none/such': No such file or directory
67 if test -w /dev/full && test -c /dev/full ; then
68 AT_CHECK_M4([-F /dev/full], [1], [],
69 [[m4: unable to create frozen state: No space left on device
79 # Check that large diversions are handled across freeze boundaries.
80 # Also check for escape character handling.
81 AT_TEST_FREEZE([large diversion],
82 [M4_ONE_MEG_DEFN[divert(2)f
89 ## ---------------- ##
90 ## loading format 1 ##
91 ## ---------------- ##
93 AT_SETUP([loading format 1])
97 Note: frozen.m4f was obtained by deleting unneeded lines from the output of
98 a version of m4 1.4.5 with changeword support. Deleting lines is in effect
99 equivalent to using undefine(name) in the input. This test ensures we
100 behave well with the old format, including \ parsing, disappearing builtins
101 (okay so long as the input does not try to use them), and restoring sane
102 defaults for features that were only added in version 2 frozen format.
104 $ m4 --version | head -n1
110 pushdef(`foo', `bar${1}')
111 define(`my_define', defn(`define'))
112 define(`my_changeword', defn(`changeword'))
113 pushdef(`my_define', `define')
114 pushdef(`my_define', defn(`define'))
119 changecom([/*], [*/])dnl
120 dnl Implied sequence of undefine(`name') due to hand-edits
121 $ m4 -F frozen.m4f frozen.m4
124 AT_DATA([frozen.m4f],
125 [[# This is a frozen state file generated by GNU M4 1.4.5
134 my_changewordchangeword
153 # End of frozen state file
157 [[foo([2]) /* foo */ popdef([foo])foo
158 my_define([bar], [1])[]popdef([my_define]) bar
159 my_define([bar], [2])[]popdef([my_define]) bar
160 my_define([bar], [3])[]popdef([my_define]) bar
161 my_define([bar], [4])[]popdef([my_define]) bar
164 AT_CHECK_M4([-R frozen.m4f input.m4], [0],
165 [[bar${1} /* foo */ \n\
173 [[m4:input.m4:5: warning: popdef: undefined macro 'my_define'
176 dnl Test rejection of v2 features in a v1 frozen file
177 AT_DATA([bogus.m4f], [[V1
181 AT_CHECK_M4([-R bogus.m4f], [1], [],
182 [[m4:bogus.m4f:2: ill-formed frozen file, version 2 directive `M' encountered
188 ## ---------------- ##
189 ## loading format 2 ##
190 ## ---------------- ##
192 AT_SETUP([loading format 2])
193 AT_KEYWORDS([frozen])
195 AT_DATA([frozen.m4f],
196 [[# Handcrafted file, obeying the version 2 spec
198 # missing close quote should be supplied
202 # missing close comment should be supplied
214 # Text to negative diversion must not crash. Catches a regression
215 # introduced 2007-05-28 and fixed 2007-05-31.
218 # Check line continuations.
222 # Zero can be implied
225 # Testing escape sequences
229 # Long macro definition. Catches a regression introduced on 2007-01-20
230 # and patched 2007-02-25.
233 01234567890123456789012345678901234567890123456789
234 01234567890123456789012345678901234567890123456789
239 [[< comment: builtin()
240 builtin(>define', foo, bar)
245 AT_CHECK_M4([-R frozen.m4f input.m4], [0],
246 [[< comment: builtin()
253 dnl We don't support anything larger than format 2; make sure of that...
254 AT_DATA([bogus.m4f], [[# comments aren't continued\
257 AT_CHECK_M4([-R bogus.m4f], [63], [],
258 [[m4:bogus.m4f:2: frozen file version 3 greater than max supported of 2
261 dnl Check that V appears.
262 AT_DATA([bogus.m4f], [[# not really a frozen file
265 AT_CHECK_M4([-R bogus.m4f], [1], [],
266 [[m4:bogus.m4f:2: expecting character `V' in frozen file
269 dnl M4_DIVNUM_TEST(number, [out-of-bounds])
270 dnl Check for diversion number corner case handling. Simulate freezing with
271 dnl number as the active diversion, then reload and check that number. If
272 dnl OUT-OF-BOUNDS, expect reloading to reject the frozen file.
273 m4_define([M4_DIVNUM_TEST], [
274 AT_DATA([frozen.m4f], [[V2
301 AT_CHECK_M4([-R frozen.m4f in.m4], m4_ifval([$2], [1], [0]),
302 m4_ifval([$2], [], [m4_bpatsubst([$1], [^0*])
303 m4_if(m4_substr([$1], [0], [1]), [-], [], [[hi
304 ]])]), m4_ifval([$2], [[m4:frozen.m4f:24: integer overflow in frozen file
308 AT_DATA([in.m4], [[define(d,divnum)divert(0)d
310 M4_DIVNUM_TEST([02147483647])
311 M4_DIVNUM_TEST([02147483648], [:])
312 M4_DIVNUM_TEST([-2147483648])
313 M4_DIVNUM_TEST([-2147483649], [:])
322 # Check that changecom/changequote are maintained across freeze boundaries.
323 AT_TEST_FREEZE([reloading changecom],
324 [[changecom`'changequote(<,>)dnl
326 [[define(<foo>, <bar>)
334 # Check that changesyntax is maintained across freeze boundaries.
335 AT_TEST_FREEZE([reloading changesyntax],
336 [[changesyntax(`W+.', `({', `)}')dnl
337 define{`a.b', `hello $1'}dnl
346 # Check that debugmode can be preserved, and how it interacts with -d
347 AT_SETUP([reloading debugmode])
348 AT_KEYWORDS([frozen])
353 AT_DATA([unfrozen.m4],
354 [[traceon(`len')len(`a')
357 AT_CHECK_M4([-F frozen.m4f -d-V frozen.m4], [0])
359 dnl With no -d option, use the frozen file
360 AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0], [[1
361 ]], [[m4trace:unfrozen.m4:1: -1- len
364 dnl With plain -d before -R, use the frozen file
365 AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0], [[1
366 ]], [[m4trace:unfrozen.m4:1: -1- len
369 dnl With plain -d after -R, add +adeq to the frozen file
370 AT_CHECK_M4([-R frozen.m4f -d unfrozen.m4], [0], [[1
371 ]], [[m4trace:unfrozen.m4:1: -1- len(`a') -> `1'
374 dnl With explicit -d option, override frozen file
375 AT_CHECK_M4([-R frozen.m4f -de unfrozen.m4], [0], [[1
376 ]], [[m4trace: -1- len -> 1
385 # Check that NUL can be transparently preserved over freezing.
386 AT_SETUP([reloading nul])
387 AT_KEYWORDS([frozen])
389 dnl AT_DATA can't generate NUL bytes (at least, not in all shells).
390 # Skip the test if printf(1) is insufficient.
391 AT_CHECK([printf 'define(-\0-,\0-\0)changequote([,\0])changecom(--\0)dnl
392 divert(1)undivert(null.out)' || exit 77],
393 [0], [stdout], [ignore])
395 printf 'divert(0)[divnum\0] @%:@-- len(indir(-\0-))\n' > unfrozen.m4
397 # First generate the `expout' output by running over the sources before
399 AT_CHECK_M4([-I "$abs_srcdir" frozen.m4 unfrozen.m4], [0], [stdout], [stderr])
404 # Now freeze the first source file.
405 AT_CHECK_M4([-F frozen.m4f -I "$abs_srcdir" frozen.m4], [0], [stdout])
409 # Now rerun the original sequence, but using the frozen file.
410 AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0], [stdout], [experr], [], [ ])
412 AT_CHECK([cat out1 stdout], [0], [expout])
414 dnl Check that unexpected embedded NULs are recognized.
415 printf '# bogus frozen file\nV2\nR4\ngnu\0\n' > bogus.m4f
416 AT_CHECK_M4([-R bogus.m4f], [1], [],
417 [[m4:bogus.m4f:4: bad syntax-spec 'gnu\0'
420 dnl Reject escape sequences that expand to unexpected NUL
422 [[# bogus frozen file
428 AT_CHECK_M4([-R bogus.m4f], [1], [],
429 [[m4:bogus.m4f:5: ill-formed frozen file, invalid builtin 'len\0' encountered
439 # Check for pushdef stacks; broken 2001-09-01, fixed 2008-05-15.
440 AT_TEST_FREEZE([reloading pushdef stack],
441 [[pushdef(`foo', `1')
442 pushdef(`foo', defn(`len'))
445 [[foo(`abc')popdef(`foo')
446 foo(`ab')popdef(`foo')
447 foo(`a')popdef(`foo')
455 # Check that regular expression syntax is maintained across freeze boundaries.
456 AT_TEST_FREEZE([reloading regexp syntax],
457 [[changeresyntax(`POSIX_EXTENDED')dnl
459 [[regexp(`GNUs not Unix', `\w(\w*)$')
460 regexp(`GNUs not Unix', `\w\(\w*\)$', `GNU_M4')
467 # Check for macro tracing, both single and global.
468 AT_TEST_FREEZE([reloading traced macros],
469 [[define(`text', `hello world')dnl
470 define(`foo', `bar')dnl
471 traceon(`blah', `divnum', `text')dnl
479 ifdef(`blah', `', `define(`blah', `finally')')dnl
483 ## ---------------- ##
484 ## unknown builtins ##
485 ## ---------------- ##
487 AT_SETUP([reloading unknown builtin])
488 AT_KEYWORDS([frozen])
490 AT_DATA([[empty.m4]])
492 # Freeze default state. Also check for bug fixed 18 Oct, 2007.
493 AT_CHECK_M4([-F frozen.m4f -t undefined empty.m4])
495 # Add an unknown builtin.
496 echo 'F1,1' >> frozen.m4f
497 echo 'a' >> frozen.m4f
498 echo 'b' >> frozen.m4f
500 AT_DATA([[input.m4]],
501 [[dnl The macro is defined; checking this is safe
502 ifdef(`a', `yes', `no')
503 dnl Grabbing the definition must warn; and the copy is the empty string
504 define(`c', defn(`a'))
505 dnl Invoking the macro directly must warn
507 dnl Invoking it indirectly must warn
509 dnl Since it is a placeholder, builtin must reject it
511 dnl The copy is a text string, not a placeholder
513 dnl Since it is defined, it must have a definition
515 dnl Deleting it is safe
520 AT_CHECK_M4([-R frozen.m4f input.m4], 0,
531 [[m4:input.m4:4: warning: defn: a: builtin 'b' requested by frozen file not found
532 m4:input.m4:6: warning: a: builtin 'b' requested by frozen file not found
533 m4:input.m4:8: warning: a: builtin 'b' requested by frozen file not found
534 m4:input.m4:10: warning: builtin: undefined builtin 'b'