aboutsummaryrefslogtreecommitdiff
path: root/tests/buildfile-scanner
diff options
context:
space:
mode:
Diffstat (limited to 'tests/buildfile-scanner')
-rw-r--r--tests/buildfile-scanner/buildfile7
-rw-r--r--tests/buildfile-scanner/driver.cxx106
-rw-r--r--tests/buildfile-scanner/testscript342
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
+}