/* Ousía Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include namespace ousia { static TerminalLogger logger(std::cerr, true); // static ConcreteLogger logger; namespace { enum class OsxmlEvent { COMMAND_START, ANNOTATION_START, ANNOTATION_END, RANGE_END, DATA }; class TestOsxmlEventListener : public OsxmlEvents { public: std::vector> events; void commandStart(const Variant &name, const Variant::mapType &args) override { events.emplace_back(OsxmlEvent::COMMAND_START, Variant::arrayType{name, args}); } void annotationStart(const Variant &className, const Variant::mapType &args) override { events.emplace_back(OsxmlEvent::ANNOTATION_START, Variant::arrayType{className, args}); } void annotationEnd(const Variant &className, const Variant::mapType &args) override { events.emplace_back(OsxmlEvent::ANNOTATION_END, Variant::arrayType{className, args}); } void rangeEnd() override { events.emplace_back(OsxmlEvent::RANGE_END, Variant::arrayType{}); } void data(const TokenizedData &data) override { Token token; Variant text; TokenizedDataReader reader = data.reader(); reader.read(token, TokenSet{}, WhitespaceMode::PRESERVE); EXPECT_EQ(Tokens::Data, token.id); text = Variant::fromString(token.content); text.setLocation(token.getLocation()); events.emplace_back(OsxmlEvent::DATA, Variant::arrayType{text}); } }; static std::vector> parseXml( const char *testString) { TestOsxmlEventListener listener; CharReader reader(testString); OsxmlEventParser parser(reader, listener, logger); parser.parse(); return listener.events; } } TEST(OsxmlEventParser, simpleCommandWithArgs) { const char *testString = ""; // 01234567 89012 3456 78 9012 34 5678 90123 456 // 0 1 2 3 std::vector> expectedEvents{ {OsxmlEvent::COMMAND_START, Variant::arrayType{ "a", Variant::mapType{ {"name", "test"}, {"a", 1}, {"b", 2}, {"c", "blub"}}}}, {OsxmlEvent::RANGE_END, Variant::arrayType{}}}; auto events = parseXml(testString); ASSERT_EQ(expectedEvents, events); // Check the locations (I'll do this one time and then just assume it works) ASSERT_EQ(1U, events[0].second.asArray()[0].getLocation().getStart()); ASSERT_EQ(2U, events[0].second.asArray()[0].getLocation().getEnd()); ASSERT_EQ( 9U, events[0].second.asArray()[1].asMap()["name"].getLocation().getStart()); ASSERT_EQ( 13U, events[0].second.asArray()[1].asMap()["name"].getLocation().getEnd()); ASSERT_EQ( 18U, events[0].second.asArray()[1].asMap()["a"].getLocation().getStart()); ASSERT_EQ( 19U, events[0].second.asArray()[1].asMap()["a"].getLocation().getEnd()); ASSERT_EQ( 24U, events[0].second.asArray()[1].asMap()["b"].getLocation().getStart()); ASSERT_EQ( 25U, events[0].second.asArray()[1].asMap()["b"].getLocation().getEnd()); ASSERT_EQ( 30U, events[0].second.asArray()[1].asMap()["c"].getLocation().getStart()); ASSERT_EQ( 34U, events[0].second.asArray()[1].asMap()["c"].getLocation().getEnd()); } TEST(OsxmlEventParser, magicTopLevelTag) { const char *testString = ""; std::vector> expectedEvents{ {OsxmlEvent::COMMAND_START, Variant::arrayType{{"a", Variant::mapType{}}}}, {OsxmlEvent::RANGE_END, Variant::arrayType{}}, {OsxmlEvent::COMMAND_START, Variant::arrayType{{"b", Variant::mapType{}}}}, {OsxmlEvent::RANGE_END, Variant::arrayType{}}}; auto events = parseXml(testString); ASSERT_EQ(expectedEvents, events); } TEST(OsxmlEventParser, magicTopLevelTagInside) { const char *testString = ""; std::vector> expectedEvents{ {OsxmlEvent::COMMAND_START, Variant::arrayType{{"a", Variant::mapType{}}}}, {OsxmlEvent::COMMAND_START, Variant::arrayType{{"ousia", Variant::mapType{}}}}, {OsxmlEvent::RANGE_END, Variant::arrayType{}}, {OsxmlEvent::RANGE_END, Variant::arrayType{}}}; auto events = parseXml(testString); ASSERT_EQ(expectedEvents, events); } TEST(OsxmlEventParser, commandWithData) { const char *testString = " hello \n world "; // 012345678901 234567890123 // 0 1 2 std::vector> expectedEvents{ {OsxmlEvent::COMMAND_START, Variant::arrayType{"a", Variant::mapType{}}}, {OsxmlEvent::DATA, Variant::arrayType{" hello \n world "}}, {OsxmlEvent::RANGE_END, Variant::arrayType{}}}; auto events = parseXml(testString); ASSERT_EQ(expectedEvents, events); // Check the location of the text ASSERT_EQ(3U, events[1].second.asArray()[0].getLocation().getStart()); ASSERT_EQ(20U, events[1].second.asArray()[0].getLocation().getEnd()); } }