// file : tests/parser/driver.cxx // copyright : Copyright (c) 2013-2017 Code Synthesis Tools CC // license : MIT; see accompanying LICENSE file #ifdef NDEBUG # error tests require enabled assert(); un-define the NDEBUG macro #endif #include #include #include #include #include #include using namespace std; using namespace xml; int main () { // Test error handling. // try { istringstream is ("X"); parser p (is, "test"); assert (p.next () == parser::start_element); assert (p.next () == parser::start_element); assert (p.next () == parser::characters && p.value () == "X"); p.next (); assert (false); } catch (const xml::exception&) { // cerr << e.what () << endl; } try { istringstream is (""); parser p (is, "test"); is.setstate (ios_base::badbit); p.next (); assert (false); } catch (const xml::exception&) { } // Test the next_expect() functionality. // { istringstream is (""); parser p (is, "test"); p.next_expect (parser::start_element, "root"); p.next_expect (parser::end_element); } try { istringstream is (""); parser p (is, "test"); p.next_expect (parser::end_element); assert (false); } catch (const xml::exception&) { // cerr << e.what () << endl; } try { istringstream is (""); parser p (is, "test"); p.next_expect (parser::start_element, "root1"); assert (false); } catch (const xml::exception&) { // cerr << e.what () << endl; } // Test next_expect() with content setting. // { istringstream is (" "); parser p (is, "empty"); p.next_expect (parser::start_element, "root", content::empty); p.next_expect (parser::end_element); p.next_expect (parser::eof); } // Test namespace declarations. // { // Followup end element event that should be precedeeded by end // namespace declaration. // istringstream is (""); parser p (is, "test", parser::receive_default | parser::receive_namespace_decls); p.next_expect (parser::start_element, "root"); p.next_expect (parser::start_namespace_decl); p.next_expect (parser::end_namespace_decl); p.next_expect (parser::end_element); } // Test value extraction. // { istringstream is ("123"); parser p (is, "test"); p.next_expect (parser::start_element, "root"); p.next_expect (parser::characters); assert (p.value () == 123); p.next_expect (parser::end_element); } // Test attribute maps. // { istringstream is (""); parser p (is, "test"); p.next_expect (parser::start_element, "root"); assert (p.attribute ("a") == "a"); assert (p.attribute ("b", "B") == "b"); assert (p.attribute ("c", "C") == "C"); assert (p.attribute ("d") == 123); assert (p.attribute ("t") == true); assert (p.attribute ("f", false) == false); p.next_expect (parser::end_element); } { istringstream is (""); parser p (is, "test"); p.next_expect (parser::start_element, "root"); assert (p.attribute ("a") == "a"); assert (p.peek () == parser::start_element && p.name () == "nested"); assert (p.attribute ("a") == "a"); p.next_expect (parser::start_element, "nested"); assert (p.attribute ("a") == "A"); p.next_expect (parser::start_element, "inner"); assert (p.attribute ("a", "") == ""); p.next_expect (parser::end_element); assert (p.attribute ("a") == "A"); assert (p.peek () == parser::end_element); assert (p.attribute ("a") == "A"); // Still valid. p.next_expect (parser::end_element); assert (p.attribute ("a") == "a"); p.next_expect (parser::end_element); assert (p.attribute ("a", "") == ""); } try { istringstream is (""); parser p (is, "test"); p.next_expect (parser::start_element, "root"); assert (p.attribute ("a") == "a"); p.next_expect (parser::end_element); assert (false); } catch (const xml::exception&) { // cerr << e.what () << endl; } try { istringstream is (""); parser p (is, "test"); p.next_expect (parser::start_element, "root"); p.attribute ("a"); assert (false); } catch (const xml::exception&) { // cerr << e.what () << endl; } // Test peeking and getting the current event. // { istringstream is ("x"); parser p (is, "peek", parser::receive_default | parser::receive_attributes_event); assert (p.event () == parser::eof); assert (p.peek () == parser::start_element); assert (p.next () == parser::start_element); assert (p.event () == parser::start_element); assert (p.peek () == parser::start_attribute); assert (p.event () == parser::start_attribute); assert (p.next () == parser::start_attribute); assert (p.peek () == parser::characters && p.value () == "x"); assert (p.next () == parser::characters && p.value () == "x"); assert (p.event () == parser::characters && p.value () == "x"); assert (p.peek () == parser::end_attribute); assert (p.event () == parser::end_attribute); assert (p.next () == parser::end_attribute); assert (p.peek () == parser::characters && p.value () == "x"); assert (p.next () == parser::characters && p.value () == "x"); assert (p.event () == parser::characters && p.value () == "x"); assert (p.peek () == parser::start_element); assert (p.next () == parser::start_element); assert (p.event () == parser::start_element); assert (p.peek () == parser::end_element); assert (p.next () == parser::end_element); assert (p.event () == parser::end_element); assert (p.peek () == parser::end_element); assert (p.next () == parser::end_element); assert (p.event () == parser::end_element); assert (p.peek () == parser::eof); assert (p.next () == parser::eof); assert (p.event () == parser::eof); } // Test content processing. // // empty // { istringstream is (" \n\t "); parser p (is, "empty", parser::receive_default | parser::receive_attributes_event); assert (p.next () == parser::start_element); p.content (content::empty); assert (p.next () == parser::start_attribute); assert (p.next () == parser::characters && p.value () == " x "); assert (p.next () == parser::end_attribute); assert (p.next () == parser::end_element); assert (p.next () == parser::eof); } try { istringstream is (" \n & X \t "); parser p (is, "empty"); assert (p.next () == parser::start_element); p.content (content::empty); p.next (); assert (false); } catch (const xml::exception&) { // cerr << e.what () << endl; } // simple // { istringstream is (" X "); parser p (is, "simple"); assert (p.next () == parser::start_element); p.content (content::simple); assert (p.next () == parser::characters && p.value () == " X "); assert (p.next () == parser::end_element); assert (p.next () == parser::eof); } try { istringstream is (" ? "); parser p (is, "simple"); assert (p.next () == parser::start_element); p.content (content::simple); assert (p.next () == parser::characters && p.value () == " ? "); p.next (); assert (false); } catch (const xml::exception&) { // cerr << e.what () << endl; } { // Test content accumulation in simple content. // istringstream is ("123"); parser p (is, "simple", parser::receive_default | parser::receive_namespace_decls); assert (p.next () == parser::start_element); p.next_expect (parser::start_namespace_decl); p.content (content::simple); assert (p.next () == parser::characters && p.value () == "123"); p.next_expect (parser::end_namespace_decl); assert (p.next () == parser::end_element); assert (p.next () == parser::eof); } try { // Test error handling in accumulation in simple content. // istringstream is ("123"); parser p (is, "simple", parser::receive_default | parser::receive_namespace_decls); assert (p.next () == parser::start_element); p.next_expect (parser::start_namespace_decl); p.content (content::simple); p.next (); assert (false); } catch (const xml::exception&) { // cerr << e.what () << endl; } // complex // { istringstream is ("\n" " \n" " \n" " X \n" " \n" "\n"); parser p (is, "complex", parser::receive_default | parser::receive_attributes_event); assert (p.next () == parser::start_element); // root p.content (content::complex); assert (p.next () == parser::start_attribute); assert (p.next () == parser::characters && p.value () == " x "); assert (p.next () == parser::end_attribute); assert (p.next () == parser::start_element); // nested p.content (content::complex); assert (p.next () == parser::start_element); // inner p.content (content::empty); assert (p.next () == parser::end_element); // inner assert (p.next () == parser::start_element); // inner p.content (content::simple); assert (p.next () == parser::characters && p.value () == " X "); assert (p.next () == parser::end_element); // inner assert (p.next () == parser::end_element); // nested assert (p.next () == parser::end_element); // root assert (p.next () == parser::eof); } try { istringstream is (" \n X X "); parser p (is, "complex"); assert (p.next () == parser::start_element); p.content (content::complex); assert (p.next () == parser::start_element); assert (p.next () == parser::end_element); p.next (); assert (false); } catch (const xml::exception&) { // cerr << e.what () << endl; } // Test element with simple content helpers. // { istringstream is ("" " X" " " " 123" " Y" " Z" " 234" " 345" " A" " B" " A" " B" " 1" " 2" " 1" " 2" ""); parser p (is, "element"); p.next_expect (parser::start_element, "root", content::complex); p.next_expect (parser::start_element, "nested"); assert (p.element () == "X"); p.next_expect (parser::start_element, "nested"); assert (p.element () == ""); p.next_expect (parser::start_element, "nested"); assert (p.element () == 123); assert (p.element ("nested") == "Y"); assert (p.element (qname ("test", "nested")) == "Z"); assert (p.element ("nested") == 234); assert (p.element (qname ("test", "nested")) == 345); assert (p.element ("nested", "a") == "A"); assert (p.element (qname ("test", "nested"), "b") == "B"); assert (p.element ("nested", "a") == "a" && p.element ("nested1") == "A"); assert (p.element (qname ("test", "nested"), "b") == "b" && p.element (qname ("test", "nested1")) == "B"); assert (p.element ("nested", 10) == 1); assert (p.element (qname ("test", "nested"), 20) == 2); assert (p.element ("nested", 10) == 10 && p.element ("nested1") == 1); assert (p.element (qname ("test", "nested"), 20) == 20 && p.element (qname ("test", "nested1")) == 2); p.next_expect (parser::end_element); } // Test the iterator interface. // { istringstream is ("X"); parser p (is, "iterator"); vector v; for (parser::iterator i (p.begin ()); i != p.end (); ++i) v.push_back (*i); //for (parser::event_type e: p) // v.push_back (e); assert (v.size () == 5); assert (v[0] == parser::start_element); assert (v[1] == parser::start_element); assert (v[2] == parser::characters); assert (v[3] == parser::end_element); assert (v[4] == parser::end_element); } // Test space extraction into the std::string value. // { istringstream is (" b "); parser p (is, "test"); p.next_expect (parser::start_element, "root"); assert (p.attribute ("a") == " a "); p.next_expect (parser::characters); assert (p.value () == " b "); p.next_expect (parser::end_element); } }