Enhance index to support starting offset.
[m4.git] / tests / freeze.at
blob693ae5435a25a265ca02a10f020830ac0752b477
1 # Hand crafted tests for GNU M4.                               -*- Autotest -*-
2 # Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
4 # This file is part of GNU M4.
6 # GNU M4 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.
11 # GNU M4 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.
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/>.
19 # AT_TEST_FREEZE([title], [text1], [text2])
20 # -----------------------------------------
21 # Create a test TITLE, which checks that freezing TEXT1, then reloading
22 # it with TEXT2, produces the same results as running TEXT1 and TEXT2 in
23 # a single run.
24 m4_define([AT_TEST_FREEZE],
25 [AT_SETUP([$1])
26 AT_KEYWORDS([frozen])
28 AT_DATA([frozen.m4], [$2])
29 AT_DATA([unfrozen.m4], [$3])
31 # First generate the `expout' output by running over the sources before
32 # freezing.
33 AT_CHECK_M4([frozen.m4 unfrozen.m4], [0], [stdout], [stderr])
35 mv stdout expout
36 mv stderr experr
38 # Now freeze the first source file.
39 AT_CHECK_M4([-F frozen.m4f frozen.m4], [0], [stdout])
41 mv stdout out1
43 # Now rerun the original sequence, but using the frozen file.
44 AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0], [stdout], [experr], [], [ ])
46 AT_CHECK([cat out1 stdout], [0], [expout])
48 AT_CLEANUP
52 AT_BANNER([Freezing state.])
54 ## ---------------- ##
55 ## freezing failure ##
56 ## ---------------- ##
58 AT_SETUP([freezing failure])
59 AT_KEYWORDS([frozen])
61 AT_CHECK_M4([-F /none/such], [1], [],
62 [[m4: cannot open `/none/such': No such file or directory
63 ]])
65 if test -w /dev/full && test -c /dev/full ; then
66   AT_CHECK_M4([-F /dev/full], [1], [],
67 [[m4: unable to create frozen state: No space left on device
68 ]])
70 AT_CLEANUP
73 ## --------------- ##
74 ## large diversion ##
75 ## --------------- ##
77 # Check that large diversions are handled across freeze boundaries.
78 # Also check for escape character handling.
79 AT_TEST_FREEZE([large diversion],
80 [M4_ONE_MEG_DEFN[divert(2)f
81 divert(1)hi
82 a\nb
83 ]],
84 [[divert(3)bye
85 ]])
87 ## ---------------- ##
88 ## loading format 1 ##
89 ## ---------------- ##
91 AT_SETUP([loading format 1])
92 AT_KEYWORDS([frozen])
94 m4_if([
95 Note: frozen.m4f was obtained by deleting unneeded lines from the output of
96 a version of m4 1.4.5 with changeword support.  Deleting lines is in effect
97 equivalent to using undefine(name) in the input.  This test ensures we
98 behave well with the old format, including \ parsing, disappearing builtins
99 (okay so long as the input does not try to use them), and restoring sane
100 defaults for features that were only added in version 2 frozen format.
102 $ m4 --version | head -n1
103 GNU M4 1.4.5
104 $ cat frozen.m4
105 divert(`-1')
106 define(`foo', `\n\
107 FOO')
108 pushdef(`foo', `bar${1}')
109 define(`my_define', defn(`define'))
110 define(`my_changeword', defn(`changeword'))
111 pushdef(`my_define', `define')
112 pushdef(`my_define', defn(`define'))
113 divert(`1')dnl
115 divert`'dnl
116 changequote([,])dnl
117 changecom([/*], [*/])dnl
118 dnl Implied sequence of undefine(`name') due to hand-edits
119 $ m4 -F frozen.m4f frozen.m4
122 AT_DATA([frozen.m4f],
123 [[# This is a frozen state file generated by GNU M4 1.4.5
125 Q1,1
127 C2,2
128 /**/
129 F6,6
130 popdefpopdef
131 F13,10
132 my_changewordchangeword
133 F9,6
134 my_definedefine
135 T9,6
136 my_definedefine
137 F9,6
138 my_definedefine
139 T3,7
140 foo\n\
142 T3,7
143 foobar${1}
144 F3,3
145 dnldnl
146 D1,8
147 bar${1}
149 D0,0
151 # End of frozen state file
154 AT_DATA([input.m4],
155 [[foo([2]) /* foo */ popdef([foo])foo
156 my_define([bar], [1])[]popdef([my_define]) bar
157 my_define([bar], [2])[]popdef([my_define]) bar
158 my_define([bar], [3])[]popdef([my_define]) bar
159 my_define([bar], [4])[]popdef([my_define]) bar
162 AT_CHECK_M4([-R frozen.m4f input.m4], [0],
163 [[bar${1} /* foo */ \n\
166 define 1
168 my_define(bar, 4) 3
169 bar${1}
171 [[m4:input.m4:5: Warning: popdef: undefined macro `my_define'
174 dnl Test rejection of v2 features in a v1 frozen file
175 AT_DATA([bogus.m4f], [[V1
179 AT_CHECK_M4([-R bogus.m4f], [1], [],
180 [[m4:bogus.m4f:2: ill-formed frozen file, version 2 directive `M' encountered
183 AT_CLEANUP
186 ## ---------------- ##
187 ## loading format 2 ##
188 ## ---------------- ##
190 AT_SETUP([loading format 2])
191 AT_KEYWORDS([frozen])
193 AT_DATA([frozen.m4f],
194 [[# Handcrafted file, obeying the version 2 spec
196 # missing close quote should be supplied
197 Q1,0
200 # missing close comment should be supplied
201 C1,0
208 F7,7,3
209 builtin
210 builtin
212 # Text to negative diversion must not crash.  Catches a regression
213 # introduced 2007-05-28 and fixed 2007-05-31.
214 D-1,5
215 12345
216 # Check line continuations.
217 D1,3
218 a\n\
220 # Zero can be implied
223 # Testing escape sequences
224 T4,5
225 blah
226 \t\477\040\X5C
227 # Long macro definition.  Catches a regression introduced on 2007-01-20
228 # and patched 2007-02-25.
229 T4,122
230 long
231 01234567890123456789012345678901234567890123456789
232 01234567890123456789012345678901234567890123456789
233 01234567890123456789
236 AT_DATA([input.m4],
237 [[< comment: builtin()
238 builtin(>define', foo, bar)
240 blah
243 AT_CHECK_M4([-R frozen.m4f input.m4], [0],
244 [[< comment: builtin()
247         '7 \
249 b]])
251 dnl We don't support anything larger than format 2; make sure of that...
252 AT_DATA([bogus.m4f], [[# comments aren't continued\
255 AT_CHECK_M4([-R bogus.m4f], [63], [],
256 [[m4:bogus.m4f:2: frozen file version 3 greater than max supported of 2
259 dnl Check that V appears.
260 AT_DATA([bogus.m4f], [[# not really a frozen file
261 oops
263 AT_CHECK_M4([-R bogus.m4f], [1], [],
264 [[m4:bogus.m4f:2: expecting character `V' in frozen file
267 dnl M4_DIVNUM_TEST(number, [out-of-bounds])
268 dnl Check for diversion number corner case handling.  Simulate freezing with
269 dnl number as the active diversion, then reload and check that number.  If
270 dnl OUT-OF-BOUNDS, expect reloading to reject the frozen file.
271 m4_define([M4_DIVNUM_TEST], [
272 AT_DATA([frozen.m4f], [[V2
277 T1,5
279 \n\n\n\n\n
280 F6,6,2
281 divnum\
283 divnum
287 F6,6,2
288 divert
289 divert
291 F6,6,2
292 define
293 define
295 D]$1[,3
299 AT_CHECK_M4([-R frozen.m4f in.m4], m4_ifval([$2], [1], [0]),
300 m4_ifval([$2], [], [m4_bpatsubst([$1], [^0*])
301 m4_if(m4_substr([$1], [0], [1]), [-], [], [[hi
302 ]])]), m4_ifval([$2], [[m4:frozen.m4f:24: integer overflow in frozen file
303 ]]))
306 AT_DATA([in.m4], [[define(d,divnum)divert(0)d
308 M4_DIVNUM_TEST([02147483647])
309 M4_DIVNUM_TEST([02147483648], [:])
310 M4_DIVNUM_TEST([-2147483648])
311 M4_DIVNUM_TEST([-2147483649], [:])
313 AT_CLEANUP
316 ## --------- ##
317 ## changecom ##
318 ## --------- ##
320 # Check that changecom/changequote are maintained across freeze boundaries.
321 AT_TEST_FREEZE([reloading changecom],
322 [[changecom`'changequote(<,>)dnl
324 [[define(<foo>, <bar>)
325 foo # foo
328 ## ------------ ##
329 ## changesyntax ##
330 ## ------------ ##
332 # Check that changesyntax is maintained across freeze boundaries.
333 AT_TEST_FREEZE([reloading changesyntax],
334 [[changesyntax(`W+.', `({', `)}')dnl
335 define{`a.b', `hello $1'}dnl
337 [[a.b{world}
340 ## --------- ##
341 ## debugmode ##
342 ## --------- ##
344 # Check that debugmode can be preserved, and how it interacts with -d
345 AT_SETUP([reloading debugmode])
346 AT_KEYWORDS([frozen])
348 AT_DATA([frozen.m4],
349 [[debugmode(`fl')dnl
351 AT_DATA([unfrozen.m4],
352 [[traceon(`len')len(`a')
355 AT_CHECK_M4([-F frozen.m4f -d-V frozen.m4], [0])
357 dnl With no -d option, use the frozen file
358 AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0], [[1
359 ]], [[m4trace:unfrozen.m4:1: -1- len
360 ]], [], [ ])
362 dnl With plain -d before -R, use the frozen file
363 AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0], [[1
364 ]], [[m4trace:unfrozen.m4:1: -1- len
367 dnl With plain -d after -R, add +adeq to the frozen file
368 AT_CHECK_M4([-R frozen.m4f -d unfrozen.m4], [0], [[1
369 ]], [[m4trace:unfrozen.m4:1: -1- len(`a') -> `1'
370 ]], [], [ ])
372 dnl With explicit -d option, override frozen file
373 AT_CHECK_M4([-R frozen.m4f -de unfrozen.m4], [0], [[1
374 ]], [[m4trace: -1- len -> 1
377 AT_CLEANUP
379 ## --------- ##
380 ## nul bytes ##
381 ## --------- ##
383 # Check that NUL can be transparently preserved over freezing.
384 AT_SETUP([reloading nul])
385 AT_KEYWORDS([frozen])
387 dnl AT_DATA can't generate NUL bytes (at least, not in all shells).
388 # Skip the test if printf(1) is insufficient.
389 AT_CHECK([printf 'define(-\0-,\0-\0)changequote([,\0])changecom(--\0)dnl
390 divert(1)undivert(null.out)' || exit 77],
391  [0], [stdout], [ignore])
392 mv stdout frozen.m4
393 printf 'divert(0)[divnum\0] @%:@-- len(indir(-\0-))\n' > unfrozen.m4
395 # First generate the `expout' output by running over the sources before
396 # freezing.
397 AT_CHECK_M4([-I "$abs_srcdir" frozen.m4 unfrozen.m4], [0], [stdout], [stderr])
399 mv stdout expout
400 mv stderr experr
402 # Now freeze the first source file.
403 AT_CHECK_M4([-F frozen.m4f -I "$abs_srcdir" frozen.m4], [0], [stdout])
405 mv stdout out1
407 # Now rerun the original sequence, but using the frozen file.
408 AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0], [stdout], [experr], [], [ ])
410 AT_CHECK([cat out1 stdout], [0], [expout])
412 dnl Check that unexpected embedded NULs are recognized.
413 printf '# bogus frozen file\nV2\nR4\ngnu\0\n' > bogus.m4f
414 AT_CHECK_M4([-R bogus.m4f], [1], [],
415 [[m4:bogus.m4f:4: bad syntax-spec `gnu\0'
418 AT_CLEANUP
421 ## ------- ##
422 ## pushdef ##
423 ## ------- ##
425 # Check for pushdef stacks; broken 2001-09-01, fixed 2008-05-15.
426 AT_TEST_FREEZE([reloading pushdef stack],
427 [[pushdef(`foo', `1')
428 pushdef(`foo', defn(`len'))
429 pushdef(`foo', `3')
431 [[foo(`abc')popdef(`foo')
432 foo(`ab')popdef(`foo')
433 foo(`a')popdef(`foo')
437 ## ------------- ##
438 ## regexp syntax ##
439 ## ------------- ##
441 # Check that regular expression syntax is maintained across freeze boundaries.
442 AT_TEST_FREEZE([reloading regexp syntax],
443 [[changeresyntax(`POSIX_EXTENDED')dnl
445 [[regexp(`GNUs not Unix', `\w(\w*)$')
446 regexp(`GNUs not Unix', `\w\(\w*\)$', `GNU_M4')
449 ## ----- ##
450 ## trace ##
451 ## ----- ##
453 # Check for macro tracing, both single and global.
454 AT_TEST_FREEZE([reloading traced macros],
455 [[define(`text', `hello world')dnl
456 define(`foo', `bar')dnl
457 traceon(`blah', `divnum', `text')dnl
458 traceon
460 [[foo
461 traceoff
463 text
464 divnum
465 ifdef(`blah', `', `define(`blah', `finally')')dnl
466 blah
469 ## ---------------- ##
470 ## unknown builtins ##
471 ## ---------------- ##
473 AT_SETUP([reloading unknown builtin])
474 AT_KEYWORDS([frozen])
476 AT_DATA([[empty.m4]])
478 # Freeze default state.  Also check for bug fixed 18 Oct, 2007.
479 AT_CHECK_M4([-F frozen.m4f -t undefined empty.m4])
481 # Add an unknown builtin.
482 echo 'F1,1' >> frozen.m4f
483 echo 'a' >> frozen.m4f
484 echo 'b' >> frozen.m4f
486 AT_DATA([[input.m4]],
487 [[dnl The macro is defined; checking this is safe
488 ifdef(`a', `yes', `no')
489 dnl Grabbing the definition must warn; and the copy is the empty string
490 define(`c', defn(`a'))
491 dnl Invoking the macro directly must warn
493 dnl Invoking it indirectly must warn
494 indir(`a')
495 dnl Since it is a placeholder, builtin must reject it
496 builtin(`b')
497 dnl The copy is a text string, not a placeholder
499 dnl Since it is defined, it must have a definition
500 dumpdef(`a', `c')
501 dnl Deleting it is safe
502 popdef(`a')
506 AT_CHECK_M4([-R frozen.m4f input.m4], 0,
507 [[yes
517 [[m4:input.m4:4: Warning: defn: a: builtin `b' requested by frozen file not found
518 m4:input.m4:6: Warning: a: builtin `b' requested by frozen file not found
519 m4:input.m4:8: Warning: a: builtin `b' requested by frozen file not found
520 m4:input.m4:10: Warning: builtin: undefined builtin `b'
521 a:      <<b>>
522 c:      `'
523 ]], [], [ ])
525 AT_CLEANUP