diff options
Diffstat (limited to 'tests/buildfile-scanner')
-rw-r--r-- | tests/buildfile-scanner/buildfile | 7 | ||||
-rw-r--r-- | tests/buildfile-scanner/driver.cxx | 106 | ||||
-rw-r--r-- | tests/buildfile-scanner/testscript | 342 |
3 files changed, 455 insertions, 0 deletions
diff --git a/tests/buildfile-scanner/buildfile b/tests/buildfile-scanner/buildfile new file mode 100644 index 0000000..82f7ace --- /dev/null +++ b/tests/buildfile-scanner/buildfile @@ -0,0 +1,7 @@ +# file : tests/buildfile-scanner/buildfile +# license : MIT; see accompanying LICENSE file + +import libs = libbutl%lib{butl} +import libs += libbpkg%lib{bpkg} + +exe{driver}: {hxx cxx}{*} $libs testscript diff --git a/tests/buildfile-scanner/driver.cxx b/tests/buildfile-scanner/driver.cxx new file mode 100644 index 0000000..fec15bd --- /dev/null +++ b/tests/buildfile-scanner/driver.cxx @@ -0,0 +1,106 @@ +// file : tests/buildfile-scanner/driver.cxx -*- C++ -*- +// license : MIT; see accompanying LICENSE file + +#include <ios> // ios_base::failbit, ios_base::badbit +#include <string> +#include <iostream> + +#include <libbutl/utf8.hxx> +#include <libbutl/utility.hxx> // operator<<(ostream,exception) +#include <libbutl/char-scanner.hxx> + +#include <libbpkg/buildfile-scanner.hxx> + +#undef NDEBUG +#include <cassert> + +using namespace std; +using namespace butl; +using namespace bpkg; + +// Usages: +// +// argv[0] (-e|-l [<char>]|-b) +// +// Read and scan the buildfile from stdin and print the scan result to stdout. +// +// -e scan evaluation context +// -l [<char>] scan single line, optionally terminated with the stop character +// -b scan buildfile block +// +int +main (int argc, char* argv[]) +{ + assert (argc >= 2); + + string mode (argv[1]); + + cin.exceptions (ios_base::failbit | ios_base::badbit); + cout.exceptions (ios_base::failbit | ios_base::badbit); + + using scanner = char_scanner<utf8_validator>; + + scanner s (cin); + + string bsn ("stdin"); + buildfile_scanner<utf8_validator, 1> bs (s, bsn); + + try + { + string r; + + if (mode == "-e") + { + scanner::xchar c (s.get ()); + assert (c == '('); + + r += c; + r += bs.scan_eval (); + + c = s.get (); + assert (c == ')'); + + r += c; + } + else if (mode == "-l") + { + char stop ('\0'); + + if (argc == 3) + { + const char* chr (argv[2]); + assert (chr[0] != '\0' && chr[1] == '\0'); + + stop = chr[0]; + } + + r += bs.scan_line (stop); + + scanner::xchar c (s.get ()); + assert (scanner::eos (c) || c == '\n' || (stop != '\0' && c == stop)); + } + else if (mode == "-b") + { + scanner::xchar c (s.get ()); + assert (c == '{'); + + r += c; + r += bs.scan_block (); + + assert (scanner::eos (s.peek ())); + + r += "}\n"; + } + else + assert (false); + + cout << r; + } + catch (const buildfile_scanning& e) + { + cerr << e << endl; + return 1; + } + + return 0; +} diff --git a/tests/buildfile-scanner/testscript b/tests/buildfile-scanner/testscript new file mode 100644 index 0000000..c62d6ce --- /dev/null +++ b/tests/buildfile-scanner/testscript @@ -0,0 +1,342 @@ +# file : tests/buildfile-scanner/testscript +# license : MIT; see accompanying LICENSE file + +: eval +: +{ + test.options += -e + + : basic + : + $* <<:EOF >>:EOF + ($cxx.target.class == windows) + EOF + + : single-quoted + : + $* <<:EOF >>:EOF + ($cxx.target.class == 'windows') + EOF + + : unterminated + : + $* <<:EOI 2>>EOE != 0 + ($cxx.target.class == 'windows' + EOI + stdin:1:32: error: unterminated evaluation context + EOE + + : newline + : + $* <<:EOI 2>>EOE != 0 + ($cxx.target.class == 'windows' + + EOI + stdin:1:32: error: unterminated evaluation context + EOE + + : single-quoted-newline + : + $* <<:EOF >>:EOF + ($foo == 'b + ar') + EOF + + : unterminated-single-quoted + : + $* <<EOI 2>>EOE != 0 + ($cxx.target.class == 'windows + EOI + stdin:2:1: error: unterminated single-quoted sequence + EOE + + : double-quoted + : + $* <<:EOF >>:EOF + ($foo == "b'a\"\\)r") + EOF + + : double-quoted-newline + : + $* <<:EOF >>:EOF + ($foo == "ba + r") + EOF + + : unterminated-double-quoted + : + $* <<:EOI 2>>EOE != 0 + ($cxx.target.class == "windows + EOI + stdin:1:31: error: unterminated double-quoted sequence + EOE + + : unterminated-escape + : + $* <<:EOI 2>>EOE != 0 + (foo == windows\ + EOI + stdin:1:17: error: unterminated escape sequence + EOE + + : comment + : + $* <<EOI 2>>EOE != 0 + ($cxx.target.class == #'windows' + EOI + stdin:1:33: error: unterminated evaluation context + EOE + + : multiline-comment + : + $* <<EOI 2>>EOE != 0 + ($cxx.target.class == #\ + 'windows' + #\ + EOI + stdin:3:3: error: unterminated evaluation context + EOE + + : multiline-comment-unterminated + : + $* <<EOI 2>>EOE != 0 + ($cxx.target.class == #\ + 'windows' + EOI + stdin:3:1: error: unterminated multi-line comment + EOE + + : nested + : + $* <<:EOF >>:EOF + (foo != bar(baz)fox) + EOF + + : nested-double-quoted + : + $* <<:EOF >>:EOF + (foo != "bar(b"a"z)fox") + EOF +} + +: line +: +{ + test.options += -l + + : assignment + : + $* <<EOI >>:EOO + foo = bar + EOI + foo = bar + EOO + + : no-newline + : + $* <<:EOF >>:EOF + foo = bar + EOF + + : eol + : + $* '|' <<EOI >:'foo = bar ' + foo = bar | baz + EOI + + : single-quoted + : + $* <<:EOF >>:EOF + foo = 'bar' + EOF + + : single-quoted-newline + : + $* <<EOI >>:EOO + foo = 'b + ar' + EOI + foo = 'b + ar' + EOO + + : unterminated-single-quoted + : + $* <<EOI 2>>EOE != 0 + foo = 'bar + EOI + stdin:2:1: error: unterminated single-quoted sequence + EOE + + : double-quoted + : + $* <<:EOF >>:EOF + foo = "b'a\"\\)r" + EOF + + : double-quoted-newline + : + $* <<EOI >>:EOO + foo == "ba + r" + EOI + foo == "ba + r" + EOO + + : unterminated-double-quoted + : + $* <<:EOI 2>>EOE != 0 + foo = "bar + EOI + stdin:1:11: error: unterminated double-quoted sequence + EOE + + : unterminated-escape + : + $* <<:EOI 2>>EOE != 0 + foo = bar\ + EOI + stdin:1:11: error: unterminated escape sequence + EOE + + : comment + : + $* <<EOI >>:EOO + foo = # bar + EOI + foo = # bar + EOO + + : empty-comment + : + $* <<EOI >>:EOO + foo = # + EOI + foo = # + EOO + + : multiline-comment + : + $* <<EOI >>:EOO + foo = #\ + 'windows' + #\ + EOI + foo = #\ + 'windows' + #\ + EOO + + : multiline-comment-unterminated + : + $* <<EOI 2>>EOE != 0 + foo = #\ + bar + EOI + stdin:3:1: error: unterminated multi-line comment + EOE + + : eval + : + $* <<:EOF >>:EOF + foo = bar(baz)fox + EOF + + : eval-unterminated + : + $* <<EOI 2>>EOE != 0 + foo = bar(baz + EOI + stdin:1:14: error: unterminated evaluation context + EOE + + : eval-double-quoted + : + $* <<:EOF >>:EOF + foo = "bar($baz ? b"a"z : 'bar')fox" + EOF +} + +: block +: +{ + test.options += -b + + : basic + : + $* <<EOF >>EOF + { + config.foo.bar = true + config.foo.baz = "baz" + } + EOF + + : quoted + : + $* <<EOF >>EOF + { + config.foo.bar = true + config.foo.baz = "baz + } + bar + " + } + EOF + + : nested + : + $* <<EOF >>EOF + { + config.foo.bar = true + + if ($cxx.target.class == windows) + { + config.foo.win = true + } + else + { + config.foo.win = false + } + } + EOF + + : comments + : + $* <<EOF >>EOF + { + config.foo.bar = true + + if ($cxx.target.class == windows) + { # single line + config.foo.win = true + } + else + { #\ + Multi + line + #\ + config.foo.win = false + } + } + EOF + + : non-spaces + : + $* <<EOI 2>>EOE != 0 + { + config.foo.bar = true + + box } + } box + }{ + }} + "}" + '}' + \} + }\ + (}) + EOI + stdin:13:1: error: unterminated buildfile block + EOE +} |