diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/buildfile | 3 | ||||
-rw-r--r-- | tests/manifest-parser/buildfile | 7 | ||||
-rw-r--r-- | tests/manifest-parser/driver.cxx | 207 | ||||
-rw-r--r-- | tests/manifest-roundtrip/buildfile | 8 | ||||
-rw-r--r-- | tests/manifest-roundtrip/driver.cxx | 52 | ||||
-rw-r--r-- | tests/manifest-roundtrip/manifest | 32 | ||||
-rw-r--r-- | tests/manifest-serializer/buildfile | 7 | ||||
-rw-r--r-- | tests/manifest-serializer/driver.cxx | 245 |
8 files changed, 560 insertions, 1 deletions
diff --git a/tests/buildfile b/tests/buildfile index fd2589a..84a17aa 100644 --- a/tests/buildfile +++ b/tests/buildfile @@ -2,7 +2,8 @@ # copyright : Copyright (c) 2014-2016 Code Synthesis Ltd # license : MIT; see accompanying LICENSE file -d = base64/ cpfile/ dir-iterator/ fdstream/ link/ pager/ path/ prefix-map/ \ +d = base64/ cpfile/ dir-iterator/ fdstream/ link/ manifest-parser/ \ + manifest-serializer/ manifest-roundtrip/ pager/ path/ prefix-map/ \ process/ sha256/ strcase/ timestamp/ triplet/ ./: $d diff --git a/tests/manifest-parser/buildfile b/tests/manifest-parser/buildfile new file mode 100644 index 0000000..9173bdb --- /dev/null +++ b/tests/manifest-parser/buildfile @@ -0,0 +1,7 @@ +# file : tests/manifest-parser/buildfile +# copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +# license : MIT; see accompanying LICENSE file + +exe{driver}: cxx{driver} ../../butl/lib{butl} + +include ../../butl/ diff --git a/tests/manifest-parser/driver.cxx b/tests/manifest-parser/driver.cxx new file mode 100644 index 0000000..bab60a8 --- /dev/null +++ b/tests/manifest-parser/driver.cxx @@ -0,0 +1,207 @@ +// file : tests/manifest-parser/driver.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include <vector> +#include <string> +#include <utility> // pair +#include <cassert> +#include <sstream> +#include <iostream> + +#include <butl/manifest-parser> + +using namespace std; +using namespace butl; + +using pairs = vector<pair<string, string>>; + +static bool +test (const char* manifest, const pairs& expected); + +static bool +fail (const char* manifest); + +int +main () +{ + // Whitespaces and comments. + // + assert (test (" \t", {{"",""}})); + assert (test (" \t\n \n\n", {{"",""}})); + assert (test ("# one\n #two", {{"",""}})); + + // Test encountering eos at various points. + // + assert (test ("", {{"",""}})); + assert (test (" ", {{"",""}})); + assert (test ("\n", {{"",""}})); + assert (fail ("a")); + assert (test (":1\na:", {{"","1"},{"a", ""},{"",""},{"",""}})); + + // Invalid manifests. + // + assert (fail ("a:")); // format version pair expected + assert (fail (":")); // format version value expected + assert (fail (":9")); // unsupported format version + assert (fail ("a")); // ':' expected after name + assert (fail ("a b")); // ':' expected after name + assert (fail ("a\tb")); // ':' expected after name + assert (fail ("a\nb")); // ':' expected after name + assert (fail (":1\na:b\n:9")); // unsupported format version + + // Empty manifest. + // + assert (test (":1", {{"","1"},{"",""},{"",""}})); + assert (test (" \t :1", {{"","1"},{"",""},{"",""}})); + assert (test (" \t : 1", {{"","1"},{"",""},{"",""}})); + assert (test (" \t : 1 ", {{"","1"},{"",""},{"",""}})); + assert (test (":1\n", {{"","1"},{"",""},{"",""}})); + assert (test (":1 \n", {{"","1"},{"",""},{"",""}})); + + // Single manifest. + // + assert (test (":1\na:x", {{"","1"},{"a", "x"},{"",""},{"",""}})); + assert (test (":1\na:x\n", {{"","1"},{"a","x"},{"",""},{"",""}})); + assert (test (":1\na:x\nb:y", + {{"","1"},{"a","x"},{"b","y"},{"",""},{"",""}})); + assert (test (":1\na:x\n\tb : y\n #comment", + {{"","1"},{"a","x"},{"b","y"},{"",""},{"",""}})); + + // Multiple manifests. + // + assert (test (":1\na:x\n:\nb:y", + {{"","1"},{"a", "x"},{"",""}, + {"","1"},{"b", "y"},{"",""},{"",""}})); + assert (test (":1\na:x\n:1\nb:y", + {{"","1"},{"a", "x"},{"",""}, + {"","1"},{"b", "y"},{"",""},{"",""}})); + assert (test (":1\na:x\n:\nb:y\n:\nc:z\n", + {{"","1"},{"a", "x"},{"",""}, + {"","1"},{"b", "y"},{"",""}, + {"","1"},{"c", "z"},{"",""},{"",""}})); + + // Name parsing. + // + assert (test (":1\nabc:", {{"","1"},{"abc",""},{"",""},{"",""}})); + assert (test (":1\nabc :", {{"","1"},{"abc",""},{"",""},{"",""}})); + assert (test (":1\nabc\t:", {{"","1"},{"abc",""},{"",""},{"",""}})); + + // Simple value parsing. + // + assert (test (":1\na: \t xyz \t ", {{"","1"},{"a","xyz"},{"",""},{"",""}})); + + // Simple value escaping. + // + assert (test (":1\na:x\\", {{"","1"},{"a","x"},{"",""},{"",""}})); + assert (test (":1\na:x\\\ny", {{"","1"},{"a","xy"},{"",""},{"",""}})); + assert (test (":1\na:x\\\\\nb:", + {{"","1"},{"a","x\\"},{"b",""},{"",""},{"",""}})); + assert (test (":1\na:x\\\\\\\nb:", + {{"","1"},{"a","x\\\\"},{"b",""},{"",""},{"",""}})); + + // Simple value literal newline. + // + assert (test (":1\na:x\\\n\\", {{"","1"},{"a","x\n"},{"",""},{"",""}})); + assert (test (":1\na:x\\\n\\\ny", {{"","1"},{"a","x\ny"},{"",""},{"",""}})); + assert (test (":1\na:x\\\n\\\ny\\\n\\\nz", + {{"","1"},{"a","x\ny\nz"},{"",""},{"",""}})); + + // Multi-line value parsing. + // + assert (test (":1\na:\\", {{"","1"},{"a", ""},{"",""},{"",""}})); + assert (test (":1\na:\\\n", {{"","1"},{"a", ""},{"",""},{"",""}})); + assert (test (":1\na:\\x", {{"","1"},{"a", "\\x"},{"",""},{"",""}})); + assert (test (":1\na:\\\n\\", {{"","1"},{"a", ""},{"",""},{"",""}})); + assert (test (":1\na:\\\n\\\n", {{"","1"},{"a", ""},{"",""},{"",""}})); + assert (test (":1\na:\\\n\\x\n\\", + {{"","1"},{"a", "\\x"},{"",""},{"",""}})); + assert (test (":1\na:\\\nx\ny", {{"","1"},{"a", "x\ny"},{"",""},{"",""}})); + assert (test (":1\na:\\\n \n#\t\n\\", + {{"","1"},{"a", " \n#\t"},{"",""},{"",""}})); + assert (test (":1\na:\\\n\n\n\\", {{"","1"},{"a", "\n"},{"",""},{"",""}})); + + // Multi-line value escaping. + // + assert (test (":1\na:\\\nx\\", {{"","1"},{"a","x"},{"",""},{"",""}})); + assert (test (":1\na:\\\nx\\\ny\n\\", + {{"","1"},{"a","xy"},{"",""},{"",""}})); + assert (test (":1\na:\\\nx\\\\\n\\\nb:", + {{"","1"},{"a","x\\"},{"b",""},{"",""},{"",""}})); + assert (test (":1\na:\\\nx\\\\\\\n\\\nb:", + {{"","1"},{"a","x\\\\"},{"b",""},{"",""},{"",""}})); +} + +static ostream& +operator<< (ostream& os, const pairs& ps) +{ + os << '{'; + + bool f (true); + for (const auto& p: ps) + os << (f ? (f = false, "") : ",") + << '{' << p.first << ',' << p.second << '}'; + + os << '}'; + return os; +} + +static pairs +parse (const char* m) +{ + istringstream is (m); + is.exceptions (istream::failbit | istream::badbit); + manifest_parser p (is, ""); + + pairs r; + + for (bool eom (true), eos (false); !eos; ) + { + manifest_name_value nv (p.next ()); + + if (nv.empty ()) // End pair. + { + eos = eom; + eom = true; + } + else + eom = false; + + r.emplace_back (nv.name, nv.value); // move + } + + return r; +} + +static bool +test (const char* m, const pairs& e) +{ + pairs r (parse (m)); + + if (r != e) + { + cerr << "actual: " << r << endl + << "expect: " << e << endl; + + return false; + } + + return true; +} + +static bool +fail (const char* m) +{ + try + { + pairs r (parse (m)); + cerr << "nofail: " << r << endl; + return false; + } + catch (const manifest_parsing& e) + { + //cerr << e.what () << endl; + } + + return true; +} diff --git a/tests/manifest-roundtrip/buildfile b/tests/manifest-roundtrip/buildfile new file mode 100644 index 0000000..78e5a08 --- /dev/null +++ b/tests/manifest-roundtrip/buildfile @@ -0,0 +1,8 @@ +# file : tests/manifest-roundtrip/buildfile +# copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +# license : MIT; see accompanying LICENSE file + +exe{driver}: cxx{driver} ../../butl/lib{butl} +exe{driver}: test.roundtrip = manifest + +include ../../butl/ diff --git a/tests/manifest-roundtrip/driver.cxx b/tests/manifest-roundtrip/driver.cxx new file mode 100644 index 0000000..e1ce5b8 --- /dev/null +++ b/tests/manifest-roundtrip/driver.cxx @@ -0,0 +1,52 @@ +// file : tests/manifest-roundtrip/driver.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include <cassert> +#include <iostream> + +#include <butl/fdstream> +#include <butl/manifest-parser> +#include <butl/manifest-serializer> + +using namespace std; +using namespace butl; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " <file>" << endl; + return 1; + } + + try + { + ifdstream ifs (argv[1]); + manifest_parser p (ifs, argv[1]); + + stdout_fdmode (fdstream_mode::binary); // Write in binary mode. + manifest_serializer s (cout, "stdout"); + + for (bool eom (true), eos (false); !eos; ) + { + manifest_name_value nv (p.next ()); + + if (nv.empty ()) // End pair. + { + eos = eom; + eom = true; + } + else + eom = false; + + s.next (nv.name, nv.value); + } + } + catch (const exception& e) + { + cerr << e.what () << endl; + return 1; + } +} diff --git a/tests/manifest-roundtrip/manifest b/tests/manifest-roundtrip/manifest new file mode 100644 index 0000000..23c2730 --- /dev/null +++ b/tests/manifest-roundtrip/manifest @@ -0,0 +1,32 @@ +: 1 +name: libbpkg +version: 1.0.1 +summary: build2 package manager library +license: MIT +tags: c++, package, manager, bpkg +description: A very very very very very very very very very very very very\ + very very very very very very very very very very very very very very very\ + very very long description. +changes: \ +1.0.1 + - Fixed a very very very very very very very very very very very very very\ + very annoying bug. +1.0.0 + - Firts public release + - Lots of really cool features +\ +url: http://www.codesynthesis.com/projects/libstudxml/ +email: build-users@codesynthesis.com; Public mailing list, posts by\ + non-members are allowed but moderated. +package-email: boris@codesynthesis.com; Direct email to the author. +depends: libbutl +depends: * build2 +depends: ?* bpkg +requires: ?* linux | windows +requires: c++11 +: +path: c:\windows\\ +path: \ + +c:\windows\\ +\ diff --git a/tests/manifest-serializer/buildfile b/tests/manifest-serializer/buildfile new file mode 100644 index 0000000..0325323 --- /dev/null +++ b/tests/manifest-serializer/buildfile @@ -0,0 +1,7 @@ +# file : tests/manifest-serializer/buildfile +# copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +# license : MIT; see accompanying LICENSE file + +exe{driver}: cxx{driver} ../../butl/lib{butl} + +include ../../butl/ diff --git a/tests/manifest-serializer/driver.cxx b/tests/manifest-serializer/driver.cxx new file mode 100644 index 0000000..250272d --- /dev/null +++ b/tests/manifest-serializer/driver.cxx @@ -0,0 +1,245 @@ +// file : tests/manifest-serializer/driver.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include <vector> +#include <string> +#include <utility> // pair +#include <cassert> +#include <sstream> +#include <iostream> + +#include <butl/manifest-serializer> + +using namespace std; +using namespace butl; + +using pairs = vector<pair<string, string>>; + +static bool +test (const pairs& manifest, const string& expected); + +static bool +fail (const pairs& manifest); + +int +main () +{ + // Comments. + // + assert (test ({{"#", ""}}, "#\n")); + assert (test ({{"#", "x"}}, "# x\n")); + assert (test ({{"#", "x"},{"#", "y"},{"#", ""}}, "# x\n# y\n#\n")); + assert (fail ({{"",""},{"#", "x"}})); // serialization after eos + + // Empty manifest stream. + // + assert (test ({}, "")); + assert (test ({{"",""}}, "")); + + // Empty manifest. + // + assert (test ({{"","1"},{"",""},{"",""}}, ": 1\n")); + assert (test ({{"","1"},{"",""},{"","1"},{"",""},{"",""}}, ": 1\n:\n")); + + // Invalid manifests. + // + assert (fail ({{"a",""}})); // format version pair expected + assert (fail ({{"","1"},{"",""},{"a",""}})); // format version pair expected + assert (fail ({{"","9"}})); // unsupported format version 9 + assert (fail ({{"","1"},{"","x"}})); // non-empty value in end pair + assert (fail ({{"",""},{"","1"}})); // serialization after eos + + // Single manifest. + // + assert (test ({{"","1"},{"a","x"},{"",""},{"",""}}, ": 1\na: x\n")); + assert (test ({{"","1"},{"a","x"},{"b","y"},{"",""},{"",""}}, + ": 1\na: x\nb: y\n")); + assert (test ({{"","1"},{"#","c"},{"a","x"},{"",""},{"",""}}, + ": 1\n# c\na: x\n")); + + // Multiple manifests. + // + assert (test ({{"","1"},{"a","x"},{"",""}, + {"","1"},{"b","y"},{"",""},{"",""}}, ": 1\na: x\n:\nb: y\n")); + assert (test ({{"","1"},{"a","x"},{"",""}, + {"","1"},{"b","y"},{"",""}, + {"","1"},{"c","z"},{"",""},{"",""}}, + ": 1\na: x\n:\nb: y\n:\nc: z\n")); + + // Invalid name. + // + assert (fail ({{"","1"},{"#a",""}})); + assert (fail ({{"","1"},{"a:b",""}})); + assert (fail ({{"","1"},{"a b",""}})); + assert (fail ({{"","1"},{"a\tb",""}})); + assert (fail ({{"","1"},{"a\n",""}})); + + // Simple value. + // + assert (test ({{"","1"},{"a",""},{"",""},{"",""}}, ": 1\na:\n")); + assert (test ({{"","1"},{"a","x y z"},{"",""},{"",""}}, ": 1\na: x y z\n")); + + // Long simple value (newline escaping). + // + + // "Solid" text/hard break. + // + string l1 ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "Yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" + "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" + "Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"); + + string e1 ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\\n" + "Yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" + "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy\\\n" + "Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"); + + // Space too early/hard break. + // + string l2 ("x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "Yyyyyyyyyyyyyyyyy yyyyyyyyyyyyyyyyyyy" + "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" + "Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz z" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"); + + string e2 ("x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\\n" + "Yyyyyyyyyyyyyyyyy yyyyyyyyyyyyyyyyyyy" + "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy\\\n" + "Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz z" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"); + + // Space/soft break. + // + string l3 ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxx" + " Yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" + "yyyyyyyyyyyyyyyyyyyyyyyyyyyyy" + " Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"); + + string e3 ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxx\\\n" + " Yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" + "yyyyyyyyyyyyyyyyyyyyyyyyyyyyy\\\n" + " Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"); + + // Space with a better one/soft break. + // + string l4 ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxx xxxxxxxxx" + " Yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" + "yyyyyyyyyyyyyyyyyy yyyyyyyyyy" + " Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"); + + string e4 ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxx xxxxxxxxx\\\n" + " Yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" + "yyyyyyyyyyyyyyyyyy yyyyyyyyyy\\\n" + " Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"); + + assert (test ({{"","1"},{"a",l1},{"",""},{"",""}}, ": 1\na: " + e1 + "\n")); + assert (test ({{"","1"},{"a",l2},{"",""},{"",""}}, ": 1\na: " + e2 + "\n")); + assert (test ({{"","1"},{"a",l3},{"",""},{"",""}}, ": 1\na: " + e3 + "\n")); + assert (test ({{"","1"},{"a",l4},{"",""},{"",""}}, ": 1\na: " + e4 + "\n")); + + + // Multi-line value. + // + string n ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + assert (test ({{"","1"},{n,"x"},{"",""},{"",""}}, + ": 1\n" + n + ": \\\nx\n\\\n")); + assert (test ({{"","1"},{"a","\n"},{"",""},{"",""}}, + ": 1\na: \\\n\n\n\\\n")); + assert (test ({{"","1"},{"a","\n\n"},{"",""},{"",""}}, + ": 1\na: \\\n\n\n\n\\\n")); + assert (test ({{"","1"},{"a","\nx\n"},{"",""},{"",""}}, + ": 1\na: \\\n\nx\n\n\\\n")); + assert (test ({{"","1"},{"a","x\ny\nz"},{"",""},{"",""}}, + ": 1\na: \\\nx\ny\nz\n\\\n")); + assert (test ({{"","1"},{"a"," x"},{"",""},{"",""}}, + ": 1\na: \\\n x\n\\\n")); + assert (test ({{"","1"},{"a","x "},{"",""},{"",""}}, + ": 1\na: \\\nx \n\\\n")); + assert (test ({{"","1"},{"a"," x "},{"",""},{"",""}}, + ": 1\na: \\\n x \n\\\n")); + + // Extra three x's are for the leading name part ("a: ") that we + // don't have. + // + assert (test ({{"","1"},{"a","\nxxx" + l1},{"",""},{"",""}}, + ": 1\na: \\\n\nxxx" + e1 + "\n\\\n")); + assert (test ({{"","1"},{"a","\nxxx" + l2},{"",""},{"",""}}, + ": 1\na: \\\n\nxxx" + e2 + "\n\\\n")); + assert (test ({{"","1"},{"a","\nxxx" + l3},{"",""},{"",""}}, + ": 1\na: \\\n\nxxx" + e3 + "\n\\\n")); + assert (test ({{"","1"},{"a","\nxxx" + l4},{"",""},{"",""}}, + ": 1\na: \\\n\nxxx" + e4 + "\n\\\n")); + + // Backslash escaping (simple and multi-line). + // + assert (test ({{"","1"},{"a","c:\\"},{"",""},{"",""}}, + ": 1\na: c:\\\\\n")); + assert (test ({{"","1"},{"a","c:\\\nd:\\"},{"",""},{"",""}}, + ": 1\na: \\\nc:\\\\\nd:\\\\\n\\\n")); +} + +static string +serialize (const pairs& m) +{ + ostringstream os; + os.exceptions (istream::failbit | istream::badbit); + manifest_serializer s (os, ""); + + for (const auto& p: m) + { + if (p.first != "#") + s.next (p.first, p.second); + else + s.comment (p.second); + } + + return os.str (); +} + +static bool +test (const pairs& m, const string& e) +{ + string r (serialize (m)); + + if (r != e) + { + cerr << "actual:" << endl << "'" << r << "'"<< endl + << "expect:" << endl << "'" << e << "'"<< endl; + + return false; + } + + return true; +} + +static bool +fail (const pairs& m) +{ + try + { + string r (serialize (m)); + cerr << "nofail: " << r << endl; + return false; + } + catch (const manifest_serialization& e) + { + //cerr << e.what () << endl; + } + + return true; +} |