tests: update `x' quotes to 'x' to match gnulib outputs.
[m4/ericb.git] / tests / freeze.at
blob4ac25d73b6a03e6f9386137cae36bae4b24c263c
1 # Hand crafted tests for GNU M4.                               -*- Autotest -*-
2 # Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation,
3 # Inc.
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
24 # a single run.
25 m4_define([AT_TEST_FREEZE],
26 [AT_SETUP([$1])
27 AT_KEYWORDS([frozen])
29 AT_DATA([frozen.m4], [$2])
30 AT_DATA([unfrozen.m4], [$3])
32 # First generate the `expout' output by running over the sources before
33 # freezing.
34 AT_CHECK_M4([frozen.m4 unfrozen.m4], [0], [stdout-nolog], [stderr])
36 mv stdout expout
37 mv stderr experr
39 # Now freeze the first source file.
40 AT_CHECK_M4([-F frozen.m4f frozen.m4], [0], [stdout-nolog])
42 mv stdout out1
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])
50 AT_CLEANUP
54 AT_BANNER([Freezing state.])
56 ## ---------------- ##
57 ## freezing failure ##
58 ## ---------------- ##
60 AT_SETUP([freezing failure])
61 AT_KEYWORDS([frozen])
63 AT_CHECK_M4([-F /none/such], [1], [],
64 [[m4: cannot open '/none/such': No such file or directory
65 ]])
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
70 ]])
72 AT_CLEANUP
75 ## --------------- ##
76 ## large diversion ##
77 ## --------------- ##
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
83 divert(1)hi
84 a\nb
85 ]],
86 [[divert(3)bye
87 ]])
89 ## ---------------- ##
90 ## loading format 1 ##
91 ## ---------------- ##
93 AT_SETUP([loading format 1])
94 AT_KEYWORDS([frozen])
96 m4_if([
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
105 GNU M4 1.4.5
106 $ cat frozen.m4
107 divert(`-1')
108 define(`foo', `\n\
109 FOO')
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'))
115 divert(`1')dnl
117 divert`'dnl
118 changequote([,])dnl
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
127 Q1,1
129 C2,2
130 /**/
131 F6,6
132 popdefpopdef
133 F13,10
134 my_changewordchangeword
135 F9,6
136 my_definedefine
137 T9,6
138 my_definedefine
139 F9,6
140 my_definedefine
141 T3,7
142 foo\n\
144 T3,7
145 foobar${1}
146 F3,3
147 dnldnl
148 D1,8
149 bar${1}
151 D0,0
153 # End of frozen state file
156 AT_DATA([input.m4],
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\
168 define 1
170 my_define(bar, 4) 3
171 bar${1}
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
185 AT_CLEANUP
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
199 Q1,0
202 # missing close comment should be supplied
203 C1,0
210 F7,7,3
211 builtin
212 builtin
214 # Text to negative diversion must not crash.  Catches a regression
215 # introduced 2007-05-28 and fixed 2007-05-31.
216 D-1,5
217 12345
218 # Check line continuations.
219 D1,3
220 a\n\
222 # Zero can be implied
225 # Testing escape sequences
226 T4,6
227 blah
228 -\t\477\040\X5C
229 # Long macro definition.  Catches a regression introduced on 2007-01-20
230 # and patched 2007-02-25.
231 T4,122
232 long
233 01234567890123456789012345678901234567890123456789
234 01234567890123456789012345678901234567890123456789
235 01234567890123456789
238 AT_DATA([input.m4],
239 [[< comment: builtin()
240 builtin(>define', foo, bar)
242 blah
245 AT_CHECK_M4([-R frozen.m4f input.m4], [0],
246 [[< comment: builtin()
249 -       '7 \
251 b]])
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
263 oops
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
279 T1,5
281 \n\n\n\n\n
282 F6,6,2
283 divnum\
285 divnum
289 F6,6,2
290 divert
291 divert
293 F6,6,2
294 define
295 define
297 D]$1[,3
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
305 ]]))
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], [:])
315 AT_CLEANUP
318 ## --------- ##
319 ## changecom ##
320 ## --------- ##
322 # Check that changecom/changequote are maintained across freeze boundaries.
323 AT_TEST_FREEZE([reloading changecom],
324 [[changecom`'changequote(<,>)dnl
326 [[define(<foo>, <bar>)
327 foo # foo
330 ## ------------ ##
331 ## changesyntax ##
332 ## ------------ ##
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
339 [[a.b{world}
342 ## --------- ##
343 ## debugmode ##
344 ## --------- ##
346 # Check that debugmode can be preserved, and how it interacts with -d
347 AT_SETUP([reloading debugmode])
348 AT_KEYWORDS([frozen])
350 AT_DATA([frozen.m4],
351 [[debugmode(`fl')dnl
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
362 ]], [], [ ])
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'
372 ]], [], [ ])
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
379 AT_CLEANUP
381 ## --------- ##
382 ## nul bytes ##
383 ## --------- ##
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])
394 mv stdout frozen.m4
395 printf 'divert(0)[divnum\0] @%:@-- len(indir(-\0-))\n' > unfrozen.m4
397 # First generate the `expout' output by running over the sources before
398 # freezing.
399 AT_CHECK_M4([-I "$abs_srcdir" frozen.m4 unfrozen.m4], [0], [stdout], [stderr])
401 mv stdout expout
402 mv stderr experr
404 # Now freeze the first source file.
405 AT_CHECK_M4([-F frozen.m4f -I "$abs_srcdir" frozen.m4], [0], [stdout])
407 mv stdout out1
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
421 AT_DATA([bogus.m4f],
422 [[# bogus frozen file
424 F3,4
426 len\0
428 AT_CHECK_M4([-R bogus.m4f], [1], [],
429 [[m4:bogus.m4f:5: ill-formed frozen file, invalid builtin 'len\0' encountered
432 AT_CLEANUP
435 ## ------- ##
436 ## pushdef ##
437 ## ------- ##
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'))
443 pushdef(`foo', `3')
445 [[foo(`abc')popdef(`foo')
446 foo(`ab')popdef(`foo')
447 foo(`a')popdef(`foo')
451 ## ------------- ##
452 ## regexp syntax ##
453 ## ------------- ##
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')
463 ## ----- ##
464 ## trace ##
465 ## ----- ##
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
472 traceon
474 [[foo
475 traceoff
477 text
478 divnum
479 ifdef(`blah', `', `define(`blah', `finally')')dnl
480 blah
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
508 indir(`a')
509 dnl Since it is a placeholder, builtin must reject it
510 builtin(`b')
511 dnl The copy is a text string, not a placeholder
513 dnl Since it is defined, it must have a definition
514 dumpdef(`a', `c')
515 dnl Deleting it is safe
516 popdef(`a')
520 AT_CHECK_M4([-R frozen.m4f input.m4], 0,
521 [[yes
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'
535 a:      <<b>>
536 c:      `'
537 ]], [], [ ])
539 AT_CLEANUP