AT_INIT AT_COLOR_TESTS # Will usually be called as # make check TESTSUITEFLAGS=--valgrind AT_ARG_OPTION([valgrind], AS_HELP_STRING([--valgrind], [Run tests under Valgrind (memcheck)])) # NOTE: We could use 1^C or 1^C^C to get an unsuccessful return code. # However, this won't print any stack trace or error message. # Therefore, we still use the idiom "(0/0)" to enforce a "Division by zero" # error whenever we want to fail. # A proper error throwing construct should be used instead once it's available. # # NOTE: By convention, we double quote the SciTECO test case # snippets, ie. put them between [[ and ]]. # The advantage is that single brackets are preserved and do not # have to be written as quadrigraphs. # Single brackets must still be balanced, so if you need an unbalanced # opening or closing bracket, you can add a ![! or !]! TECO comment # to balance the braces from the viewpoint of M4. # Round braces are preserved and do not have to be balanced. # Most test cases can use the TE_CHECK() macro below, which takes # care of escaping shell constructs. # Effectively, you can put arbitrary TECO code into TE_CHECK([[...]]) # calls and only have to take additional actions in case of unbalanced # square brackets. m4_define([TE_CHECK], [ AT_CHECK([$SCITECO --eval ']m4_bpatsubst([[$1]], ['], ['\\''])['], [$2], [$3], [$4]) ]) m4_define([TE_CHECK_CMDLINE], [ AT_CHECK([$SCITECO --no-profile --fake-cmdline ']m4_bpatsubst([[$1]], ['], ['\\''])['], [$2], [$3], [$4]) ]) # Control characters for testing immediate editing commands with TE_CHECK_CMDLINE(). # Often, we can use {...} for testing rubout, but sometimes this is not enough. # Theoretically, we could directly embed control codes, but for the time being # I am trying to keep non-TECO sources clean of non-printable characters. m4_define([TE_ESCAPE], [m4_format([%c], 27)]) m4_define([TE_RUBOUT], [m4_format([%c], 8)]) m4_define([TE_RUBOUT_WORD], [m4_format([%c], 23)]) AT_BANNER([Language features]) AT_SETUP([Number stack]) TE_CHECK([[2%a,%a - 3"N(0/0)' $]], 0, ignore, ignore) # It's not quite clear what would be the best semantics for comma: # a) Superfluous commas as in ",," or "(1,)" should be an error. # b) Superfluous commas should be ignored which is effectively what we do now. # Even then it might be advisable to treat (1,) like (1). # c) The empty "list" element is equivalent to 0, so # "1,,2" is equivalent to "1,0,2" and (1,) to (1,0). TE_CHECK([[(1,) "~|(0/0)']], 0, ignore, ignore) TE_CHECK([[1,(2)= =]], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Exit status]) TE_CHECK([[23]], 23, ignore, ignore) TE_CHECK([[42^C (0/0)]], 42, ignore, ignore) TE_CHECK([[13$$ (0/0)]], 13, ignore, ignore) TE_CHECK([[@^Um{9^C^C} Mm (0/0)]], 9, ignore, ignore) AT_CLEANUP AT_SETUP([Radix]) TE_CHECK([[0^R]], 1, ignore, ignore) TE_CHECK([[0U.^R]], 1, ignore, ignore) TE_CHECK([[23 (2^R)\^D .-5"N(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Exponentiation]) TE_CHECK([[-1^*0 - (-1)"N(0/0)']], 0, ignore, ignore) TE_CHECK([[-1^*-5 - (-1)"N(0/0)']], 0, ignore, ignore) TE_CHECK([[0^*-5=]], 1, ignore, ignore) TE_CHECK([[0^*0 - 1"N(0/0)']], 0, ignore, ignore) TE_CHECK([[1^*-5 - 1"N(0/0)']], 0, ignore, ignore) TE_CHECK([[2^*-5 - 0"N(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Missing left operand]) TE_CHECK([[+23=]], 1, ignore, ignore) AT_CLEANUP AT_SETUP([Operator precedence]) TE_CHECK([[(10-2-3)-5"N(0/0)']], 0, ignore, ignore) TE_CHECK([[(1-6*5)+29"N(0/0)']], 0, ignore, ignore) TE_CHECK([[(1-6*5-1)+30"N(0/0)']], 0, ignore, ignore) TE_CHECK([[(1-6*5-1*2*2)+33"N(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Modifiers]) TE_CHECK([[@:W$ :@W$]], 0, ignore, ignore) # Detect invalid modifiers TE_CHECK([[@J]], 1, ignore, ignore) TE_CHECK([[: ]], 1, ignore, ignore) TE_CHECK([[::C$]], 1, ignore, ignore) AT_CLEANUP AT_SETUP([Closing loops at the correct macro level]) TE_CHECK([[@^Ua{>} ]], 1, ignore, ignore) TE_CHECK([[1<23(1;)> "~|(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Pass-through loops]) # NOTE: This requires the <=>, so that values get consumed from the stack. # More elegant would be a command for popping exactly one argument like <:$>. TE_CHECK([[1,2,3,-1:<"~1;'%a=> Qa-6"N(0/0)']], 0, ignore, ignore) TE_CHECK([[1,2,3,-1:<"~1;'%a= F>(0/0)> Qa-6"N(0/0)']], 0, ignore, ignore) TE_CHECK([[3<%a:>-3"N(0/0)' $]], 0, ignore, ignore) TE_CHECK([[3<%a :F>(0/0):>-3"N(0/0)' $]], 0, ignore, ignore) AT_CLEANUP AT_SETUP([String arguments]) TE_CHECK([[Ifoo^Q]]TE_ESCAPE[[(0/0)]]TE_ESCAPE, 0, ignore, ignore) TE_CHECK([[@I"foo^Q"(0/0)"]], 0, ignore, ignore) TE_CHECK([[@I{foo{bar}foo^Q{(0/0)}]], 0, ignore, ignore) TE_CHECK([[@^Ua {12345} :Qa-5"N(0/0)']], 0, ignore, ignore) TE_CHECK([[@I/X/ H@FR{X}/12345/ Z-5"N(0/0)']], 0, ignore, ignore) TE_CHECK([[@Ia^EQa(0/0)a]], 0, ignore, ignore) # Video-TECO-like syntax - might change in the future TE_CHECK([[@I/^E<65>^E<0x41>^E<0101>/ <-A:; -A-^^A"N(0/0)' R>]], 0, ignore, ignore) # TODO: More string building constructs AT_CLEANUP AT_SETUP([Q-Register definitions]) TE_CHECK([[0Ua]], 0, ignore, ignore) TE_CHECK([[0U.a]], 0, ignore, ignore) TE_CHECK([[0U.^X]], 0, ignore, ignore) TE_CHECK([[0U#ab]], 0, ignore, ignore) TE_CHECK([[0U.#ab]], 0, ignore, ignore) TE_CHECK([[0U[AB] ]], 0, ignore, ignore) TE_CHECK([[0U.[AB] ]], 0, ignore, ignore) TE_CHECK([[![! 0U[AB^Q](0/0)] ]], 0, ignore, ignore) # TODO: String building in Q-Register definitions AT_CLEANUP AT_SETUP([Copy, append and cut to Q-Registers]) TE_CHECK([[@I/12^J123/J Xa :Xa L-:@Xa :Qa-9"N(0/0)' Z-3"N(0/0)']], 0, ignore, ignore) TE_CHECK([[@I/ABCDE/ 1,4Xa 0,3:Xa 3,5:@Xa :Qa-8"N(0/0)' Z-3"N(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Q-Register stack]) TE_CHECK([[ [a 23Ub ]b Qb"N(0/0)']], 0, ignore, ignore) # FG will temporarily change the working directory to tests/testsuite.dir. TE_CHECK([[ [$ @FG'..' ]$ :Q$-1Q$-^^r"=(0/0)']], 0, ignore, ignore) TE_CHECK([[ [: @I/XXX/ ]: ."N(0/0)']], 0, ignore, ignore) TE_CHECK([[ [a :]a"F(0/0)' ![! :]a"S(0/0)']], 0, ignore, ignore) AT_CLEANUP m4_define([TE_MAXINT32], [2147483647]) m4_define([TE_MININT32], [-2147483648]) m4_define([TE_MAXINT64], [9223372036854775807]) m4_define([TE_MININT64], [-9223372036854775808]) AT_SETUP([Formatting numbers]) # MAXINT32/MININT32: should always work. TE_CHECK(TE_MAXINT32[[\ J::@S/]]TE_MAXINT32[[/"F(0/0)']], 0, ignore, ignore) TE_CHECK(TE_MININT32[[\ J::@S/]]TE_MININT32[[/"F(0/0)']], 0, ignore, ignore) AT_SKIP_IF([test $TECO_INTEGER -lt 64]) TE_CHECK(TE_MAXINT64[[\ J::@S/]]TE_MAXINT64[[/"F(0/0)']], 0, ignore, ignore) TE_CHECK(TE_MININT64[[\ J::@S/]]TE_MININT64[[/"F(0/0)']], 0, ignore, ignore) AT_CLEANUP # This should always work, at least on systems with a two's complement # representation of negative integers. # We will probably never meet anything else, but at least we check. AT_SETUP([Integer comparisons]) TE_CHECK([[(]]TE_MAXINT32[[)-(]]TE_MAXINT32[[)"N(0/0)']], 0, ignore, ignore) TE_CHECK([[(]]TE_MININT32[[)-(]]TE_MININT32[[)"N(0/0)']], 0, ignore, ignore) AT_SKIP_IF([test $TECO_INTEGER -lt 64]) TE_CHECK([[(]]TE_MAXINT64[[)-(]]TE_MAXINT64[[)"N(0/0)']], 0, ignore, ignore) TE_CHECK([[(]]TE_MININT64[[)-(]]TE_MININT64[[)"N(0/0)']], 0, ignore, ignore) AT_CLEANUP # FIXME: Once we have a --quiet option, we should probably use it here. AT_SETUP([Printing numbers]) # Must print only one hexadecimal number. TE_CHECK([[255===]], 0, stdout, ignore) AT_FAIL_IF([test `$GREP -v "^Info:" stdout | wc -l` -ne 1], 0, ignore, ignore) # Without LF: Only the "Info:" line will be counted. TE_CHECK([[255:===]], 0, stdout, ignore) AT_FAIL_IF([test `wc -l ]], 0, stdout, ignore) AT_FAIL_IF([test `$GREP -v "^Info:" stdout | wc -l` -ne 4], 0, ignore, ignore) TE_CHECK_CMDLINE([[3<255=>]], 0, stdout, ignore) AT_FAIL_IF([test `$GREP -v "^Info:" stdout | wc -l` -ne 3], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Printing strings]) # FIXME: Test that the LF is missing at line end. TE_CHECK([[@^A/TEST^JLine 2/]], 0, stdout, ignore) AT_FAIL_IF([test `$GREP -v "^Info:" stdout | wc -l` -ne 2], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Type out buffer contents]) AT_DATA([test.txt], [[Line 1 Line 2 Line 3 ]]) TE_CHECK([[@EB'test.txt' 2T]], 0, stdout, ignore) AT_FAIL_IF([test `$GREP -v "^Info:" stdout | wc -l` -ne 2], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Type out and get char]) TE_CHECK([[1058,1045,1057,1058^T]], 0, stdout, ignore) AT_FAIL_IF([test "`$GREP -v "^Info:" stdout`" != "ТЕСТ"], 0, ignore, ignore) AT_CHECK([[printf "ТЕСТ" | $SCITECO -e '<^TUa Qa:; Qa=>']], 0, stdout, ignore) AT_FAIL_IF([test `$GREP -v "^Info:" stdout | wc -l` -ne 4], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Convert between line and glyph positions]) TE_CHECK([[@I/1^J2^J3/J 2^QC :^Q-3"N(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Moving by words]) AT_DATA([words-example.txt], [[navigating (words is useful ]]) TE_CHECK([[@EB'words-example.txt' 3J 2W @P .-17"N(0/0)']], 0, ignore, ignore) TE_CHECK([[@I/foo ^J bar/ JW @W .-Z"N(0/0)']], 0, ignore, ignore) TE_CHECK([[@EB'words-example.txt' Z-4J 3P .-12"N(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Deleting words]) AT_DATA([words-example.txt], [[navigating (words is useful ]]) TE_CHECK([[@EB'words-example.txt' 3J 2V .-3"N(0/0)' @V Z-11"N(0/0)']], 0, ignore, ignore) TE_CHECK([[@EB'words-example.txt' Z-4J 2Y .-18"N(0/0)' 2C @Y Z-19"N(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Searches]) # FIXME: We cannot currently easily insert a single ASCII 5 (^E), as it must be followed # by a 2nd character. It can be quoted, but cannot be written as Caret+E. # You also cannot search for a single ASCII 5 using Caret+E. # 2 additional ^Q are translated to a single ^Q and interpreted at the search-pattern layer. TE_CHECK(m4_format([[@I/^Q%c/ J @:S/^Q^Q^Q%c/"F(0/0)']], 5, 5), 0, ignore, ignore) # Canse-sensitive search TE_CHECK([[@I/XXX/J -^X @:S/xxx/"S(0/0)']], 0, ignore, ignore) # Search mode should be local to the macro frame. TE_CHECK([[-^X @^Um{^X} Mm-0"N(0/0)']], 0, ignore, ignore) TE_CHECK([[@I/XYZ/ J ::@S/X/"F(0/0)' H::@S/Z/"S(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Searches over buffer boundaries]) TE_CHECK([[@I/XYZ/J @EB/foo/ @I/XZY/J @:N/Z/"F(0/0)' Q*-2"N(0/0)' @:N//"F(0/0)' Q*-1"N(0/0)']], 0, ignore, ignore) TE_CHECK([[@I/XYZ/J @EB/foo/ @I/XZY/J @:FN/Z/0/"F(0/0)' Q*-2"N(0/0)' @:FN///"F(0/0)' Q*-1"N(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Search and insertion ranges]) # When deleting characters, the result of ^S/^Y must not change. TE_CHECK([[@I/XXYYZZ/^SC ."N(0/0)' C @S/YY/ HK ^YU1U0 Q0-2"N(0/0)' Q1-4"N(0/0)']], 0, ignore, ignore) TE_CHECK([[@I/XXYYZZ/J @S/XX^E[^EMY]/ 1^YXa :Qa-2"N(0/0)']], 0, ignore, ignore) TE_CHECK([[@I/XXYYZZ/J @FD/^EMZ/ ^S+2"N(0/0)']], 0, ignore, ignore) TE_CHECK([[@^Ua/XYZ/ Ga ^S+3"N(0/0)']], 0, ignore, ignore) # NOTE: EN currently inserts another trailing linefeed. TE_CHECK([[@EN/*/XYZ/ ^S+4"N(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Editing local registers in macro calls]) TE_CHECK([[@^Ua{@EQ.x//} :Ma @^U.x/FOO/]], 0, ignore, ignore) TE_CHECK([[@^Ua{@EQ.x//} Ma @^U.x/FOO/]], 1, ignore, ignore) TE_CHECK([[@^Ua{@EQ.x// Mb Q*U*} Ma]], 0, ignore, ignore) AT_CLEANUP # This is also for detecting leaks under Valgrind. AT_SETUP([Unterminated commands]) TE_CHECK([[G[foo^Q] ]], 1, ignore, ignore) TE_CHECK([[!foo ]], 1, ignore, ignore) TE_CHECK([[^Ua ]], 1, ignore, ignore) TE_CHECK([[EGa ]], 1, ignore, ignore) AT_CLEANUP AT_SETUP([Loading files into Q-Registers]) TE_CHECK([[@I/../ @EW/loadqreg.txt/ @EQa/loadqreg.txt/ :Qa-2"N(0/0)']], 0, ignore, ignore) # Does the same as FG..$. Afterwards, the parent directory should be shorter. TE_CHECK([[:Q$Ul @EQ$/loadqreg.txt/ :Q$-Ql+1">(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Saving Q-Registers contents to files]) TE_CHECK([[@^Ua/test/ @E%a/saveqreg.txt/ @EB/saveqreg.txt/ Z-4"N(0/0)']], 0, ignore, ignore) TE_CHECK([[@E%$/saveqreg.txt/ @EB/saveqreg.txt/ Z-:Q$"N(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Saving documents]) TE_CHECK([[@I/test/ @EW/savebuf.txt/ :Q*"=(0/0)']], 0, ignore, ignore) TE_CHECK([[@I/test/ @EB/foo/ 1@EW/savebuf.txt/]], 0, ignore, ignore) AT_CHECK([test `wc -c : TE_CHECK([[0EE 255@I/A/J 65001EE 0A-(-2)"N(0/0)' 1A-^^A"N(0/0)' 2A-(-1)"N(0/0)']], 0, ignore, ignore) # FIXME: Byte 128 should probably return -3 (incomplete sequence). TE_CHECK([[@EQa// 0EE 128@I/A/J 65001EE 0Qa-(-2)"N(0/0)' 1Qa-^^A"N(0/0)' 2Qa-(-1)"N(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Automatic EOL normalization]) TE_CHECK([[@EB'^EQ[$srcdir]/autoeol-input.txt' EL-2"N(0/0)' 2LR 13@I'' 0EL @EW'autoeol-sciteco.txt']], 0, ignore, ignore) AT_CHECK([[cmp autoeol-sciteco.txt ${srcdir}/autoeol-output.txt]], 0, ignore, ignore) TE_CHECK([[@EB'autoeol-sciteco.txt' EL-0"N(0/0)' 2EL @EW'']], 0, ignore, ignore) AT_CHECK([[cmp autoeol-sciteco.txt ${srcdir}/autoeol-input.txt]], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Memory limiting]) TE_CHECK([[50*1000*1000,2EJ <[a> !]!]], 1, ignore, ignore) AT_CLEANUP AT_SETUP([Change working directory]) TE_CHECK([[:Q$Ul @FG'..' Ql-:Q$-1"<(0/0)']], 0, ignore, ignore) TE_CHECK([[:Q$Ul :@^U$'/..' Ql-:Q$-1"<(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Execute external command]) # TODO: It would be a better test to generate a random number of bytes. # Unfortunately, neither $RANDOM, shuf nor jot are portable. # So we have to wait until SciTECO supports a random number generator. TE_CHECK([[@EC'dd if=/dev/zero bs=512 count=1' Z= Z-512"N(0/0)']], 0, ignore, ignore) TE_CHECK([[0,128ED @EC'dd if=/dev/zero bs=512 count=1' Z= Z-512"N(0/0)']], 0, ignore, ignore) TE_CHECK([[@I/hello/ H@EC'tr a-z A-Z' J<0A"V(0/0)' :C;>]], 0, ignore, ignore) TE_CHECK([[@I/hello^J/ -@EC'tr a-z A-Z' J<0A"V(0/0)' :C;>]], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Timestamps]) # TODO: Test the date (^B) and time (^H and :^H) variants as well. TE_CHECK([[::^HUt 100^W (::^H-Qt)-100"<(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Program version]) TE_CHECK([[EO=]], 0, stdout, ignore) # FIXME: The grep shouldn't be necessary if we run all tests with --quiet. AT_CHECK([[EO="`$GREP -v "^Info:" stdout`" && \ test $(($EO/10000)).$(($EO/100%100)).$(($EO%100)) = "$SCITECO_VERSION"]], 0, ignore, ignore) AT_CLEANUP # # Command-line editing. # # This either uses the portable $RUBOUT and $RUBOUT_WORD variables or # we use the push/pop command-line commands { and } from start states. # # NOTE: Most errors are not reported in exit codes - you must check stderr. # AT_SETUP([Rub out with immediate editing commands]) # Must rub out @, but not the colon from the Q-Reg specification. TE_CHECK_CMDLINE([[Q:@I/XXX/ ]]TE_RUBOUT_WORD[[{Z-2"N(0/0)'}]], 0, ignore, stderr) AT_FAIL_IF([$GREP "^Error:" stderr]) # Should not rub out @ and : characters. TE_CHECK_CMDLINE([[@I/ @:foo ]]TE_RUBOUT_WORD[[/ Z-3"N(0/0)']], 0, ignore, stderr) AT_FAIL_IF([$GREP "^Error:" stderr]) AT_CLEANUP AT_SETUP([Disallowed interactive commands]) # Command-line termination while editing the replacement register would # be hard to recover from. TE_CHECK_CMDLINE([[{$$}]], 0, ignore, stderr) AT_FAIL_IF([! $GREP "^Error:" stderr]) # ^C interruption should not terminate the command-line accidentally. TE_CHECK_CMDLINE([[^C]], 0, ignore, stderr) AT_FAIL_IF([! $GREP "^Error:" stderr]) # ^C^C is generally disallowed in interactive mode. TE_CHECK_CMDLINE([[@^Um{^C^C} Mm]], 0, ignore, stderr) AT_FAIL_IF([! $GREP "^Error:" stderr]) AT_CLEANUP AT_BANNER([Standard library]) AT_SETUP([Command line opener]) AT_DATA([data.123], [0123456789 9876543210 ]) AT_CHECK([[$SCITECO -e "@EI'^EQ[\$SCITECOPATH]/opener.tes' M[opener] -EF .-13\"N(0/0)'" +2,3 data.123]], 0, ignore, ignore) AT_CHECK([[$SCITECO -e "@EI'^EQ[\$SCITECOPATH]/opener.tes' M[opener] -EF .-11\"N(0/0)'" data.123:2]], 0, ignore, ignore) # `-S` stops processing of special arguments AT_CHECK([[$SCITECO -e "@EI'^EQ[\$SCITECOPATH]/opener.tes' M[opener] -EF EJ-2\"N(0/0)'" -S +1 data.123]], 0, ignore, ignore) AT_CLEANUP AT_BANNER([Regression Tests]) AT_SETUP([Glob patterns with character classes]) # Also checks closing brackets as part of the character set. TE_CHECK([[![! :@EN/*.[]ch]/foo.h/"F(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Glob patterns with unclosed trailing brackets]) TE_CHECK([[:@EN/*.[h/foo.[h/"F(0/0)' !]]!]], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Searching with large counts]) # Even though the search will be unsuccessful, it will not be considered # a proper error, so the process return code is still 0. TE_CHECK([[2147483647@S/foo/]], 0, ignore, ignore) # Will always break the memory limit which is considered an error. TE_CHECK([[-2147483648@S/foo/]], 1, ignore, ignore) AT_CLEANUP AT_SETUP([Search on new empty document]) TE_CHECK([[:@S/foo/"S(0/0)']], 0, ignore, ignore) TE_CHECK([[:@N/foo/"S(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Search for one of characters in uninitialized Q-Register]) # Register "a" exists, but it's string part is yet uninitialized. TE_CHECK([[:@S/^EGa/"S(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Search accesses wrong Q-Register table]) TE_CHECK([[@^U.#xx/123/ @^Um{:@S/^EG.#xx/$} :Mm Mm]], 1, ignore, ignore) AT_CLEANUP AT_SETUP([Invalid buffer ids]) TE_CHECK([[42@EB//]], 1, ignore, ignore) TE_CHECK([[23@EW//]], 1, ignore, ignore) TE_CHECK([[11EF]], 1, ignore, ignore) AT_CLEANUP AT_SETUP([Memory limiting during spawning]) # This might result in an OOM if memory limiting is not working TE_CHECK([[50*1000*1000,2EJ 0,128ED @EC'dd if=/dev/zero']], 1, ignore, ignore) AT_CLEANUP AT_SETUP([Memory limiting during file reading]) AT_CHECK([[dd if=/dev/zero of=big-file.txt bs=1000 count=50000]], 0, ignore, ignore) AT_CHECK([[$SCITECO -8e '50*1000*1000,2EJ @EB"big-file.txt"']], 1, ignore, ignore) AT_CLEANUP AT_SETUP([Q-Register stack cleanup]) TE_CHECK([[ [a !]!]], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Uninitialized "_"-register]) TE_CHECK([[:@S//"S(0/0)']], 0, ignore, ignore) TE_CHECK([[:@EN///"S(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Uninitialized Q-Register in string building]) TE_CHECK([[@I/^E@a/]], 0, ignore, ignore) TE_CHECK([[@I/^ENa/]], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Setting special Q-Registers with EU]) # NOTE: The clipboard registers also suffered from this, but the test suite # should not influence the clipboard (and it's not in Curses anyway). # # Should fail, but not crash TE_CHECK([[@EU*""]], 1, ignore, ignore) TE_CHECK([[@EU$"."]], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Empty help topic]) # FIXME: Produces a false positive under Valgrind # due to the value of $SCITECOPATH. TE_CHECK([[@?//]], 1, ignore, ignore) AT_CLEANUP AT_SETUP([Empty lexer name]) TE_CHECK([[@ES/SETILEXER//]], 1, ignore, ignore) AT_CLEANUP AT_SETUP([Empty command string]) TE_CHECK([[@EC//]], 1, ignore, ignore) TE_CHECK([[@EGa//]], 1, ignore, ignore) AT_CLEANUP AT_SETUP([Jump to beginning of macro]) TE_CHECK([[%a-2"< F< ' Qa-2"N(0/0)']], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Gotos and labels]) # Not a label redefinition, there must not even be a warning. TE_CHECK([[2]], 0, ignore, stderr) AT_FAIL_IF([$GREP "^Warning:" stderr]) # Will print a warning about label redefinition, though... TE_CHECK([[!foo! Qa"S^C' !foo! Qa"S(0/0)' -Ua @O/foo/]], 0, ignore, ignore) # This should not leak memory or cause memory corruptions when running under # Valgrind or Asan: TE_CHECK_CMDLINE([[!foo!{-5D}]], 0, ignore, stderr) # FIXME: Could leak memory, but we cannot detect that easily. #TE_CHECK([[!foo]], 1, ignore, ignore) AT_CLEANUP # # Command-line editing regressions: # See above for rules. # AT_SETUP([Rub out string append]) TE_CHECK_CMDLINE([[@I/XXX/ H:Xa{-4D} :Qa-0"N(0/0)']], 0, ignore, stderr) AT_FAIL_IF([$GREP "^Error:" stderr]) AT_CLEANUP AT_SETUP([Rub out of empty forward kill]) TE_CHECK_CMDLINE([[@I/F/ J @I/X/ @FK/F/{-6D} Z-2"N(0/0)']], 0, ignore, stderr) AT_FAIL_IF([$GREP "^Error:" stderr]) AT_CLEANUP AT_SETUP([Rub out Q-Register specifications]) # This was causing memory corruptions, that would at least show up under Valgrind. TE_CHECK_CMDLINE([[GaGb{-4D}]], 0, ignore, stderr) AT_FAIL_IF([$GREP "^Error:" stderr]) AT_CLEANUP AT_SETUP([Restore flags after rub out]) # Must throw an error if the @ flag is restored properly. TE_CHECK_CMDLINE([[0@W{-D}C]], 0, ignore, stderr) AT_FAIL_IF([! $GREP "^Error:" stderr]) AT_CLEANUP AT_SETUP([Rub out stack operations in macro calls]) # This was causing memory corruptions, that would at least show up under Valgrind. TE_CHECK_CMDLINE([[@^Um{[.a].b}Mm{-2D}]], 0, ignore, stderr) AT_FAIL_IF([$GREP "^Error:" stderr]) TE_CHECK_CMDLINE([[[.a@^Um{].b}Mm{-2D}]], 0, ignore, stderr) AT_FAIL_IF([$GREP "^Error:" stderr]) AT_CLEANUP AT_SETUP([Searches from macro calls]) TE_CHECK_CMDLINE([[@^Um{:@S/XXX/} :Mm"S(0/0)' Mm"S(0/0)']], 0, ignore, stderr) AT_FAIL_IF([$GREP "^Error:" stderr]) AT_CLEANUP AT_SETUP([Overwriting builtin registers]) # Initializes registers in batch mode, which are later replaced during startup # of interactive mode. # This was causing assertion errors. AT_DATA([test.tec], [[23U^[ !]! 23U~ ]]) AT_CHECK([[$SCITECO --fake-cmdline '' --mung test.tec]], 0, ignore, ignore) AT_CLEANUP AT_BANNER([Known Bugs]) AT_SETUP([Number stack]) # Nobody needs the current semantic of digit "commands" and they # will be replaced with proper number parser states, which will also allow for # floating point constants. # With the current parser, it is hard to even interpret the following code correctly... TE_CHECK([[(12)3 - 3"N(0/0)']], 0, ignore, ignore) AT_XFAIL_IF(true) AT_CLEANUP AT_SETUP([Dangling Else/End-If]) # Should throw syntax errors. TE_CHECK([[']], 1, ignore, ignore) TE_CHECK([[| (0/0) ']], 1, ignore, ignore) AT_XFAIL_IF(true) AT_CLEANUP # NOTE: This bug depends on specific build options of Glib's # PCRE which is not predictable. # It segfaults at least on Ubuntu 20.04 (libpcre3 v2:8.39). #AT_SETUP([Pattern matching overflow]) ## Should no longer dump core. ## It could fail because the memory limit is exceeed, ## but not in this case since the match string isn't too large. #TE_CHECK([[100000<@I"X">J @S"^EM^X"]], 0, ignore, ignore) #AT_XFAIL_IF(true) #AT_CLEANUP AT_SETUP([Recursion overflow]) # Should no longer dump core. # It could fail because the memory limit is exceeed, # but not in this case since we limit the recursion. TE_CHECK([[@^Um{U.a Q.a-100000"<%.aMm'} 0Mm]], 0, ignore, ignore) AT_XFAIL_IF(true) AT_CLEANUP AT_SETUP([Rub out from empty string argument]) # Should rub out the modifiers as well. # Will currently fail because it tries to execute `:@{`. TE_CHECK_CMDLINE([[:@^Ua/]]TE_RUBOUT_WORD[[{Z"N(0/0)'}]], 0, ignore, stderr) AT_CHECK([[! $GREP "^Error:" stderr]], 0, ignore, ignore) AT_XFAIL_IF(true) AT_CLEANUP AT_SETUP([Command-line termination]) # Everything after the $$ should be preserved. TE_CHECK_CMDLINE([[{@I/$$1234=/}]], 0, stdout, ignore) AT_CHECK([[$GREP "1234" stdout]], 0, ignore, ignore) AT_XFAIL_IF(true) AT_CLEANUP