[Ktutorial-commits] SF.net SVN: ktutorial:[195] trunk/ktutorial/ktutorial-editor
Status: Alpha
Brought to you by:
danxuliu
|
From: <dan...@us...> - 2010-03-26 08:49:20
|
Revision: 195
http://ktutorial.svn.sourceforge.net/ktutorial/?rev=195&view=rev
Author: danxuliu
Date: 2010-03-26 08:49:10 +0000 (Fri, 26 Mar 2010)
Log Message:
-----------
-Add TutorialReader class to deserialize a Tutorial in XML.
-Enable exceptions.
Modified Paths:
--------------
trunk/ktutorial/ktutorial-editor/CMakeLists.txt
trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt
trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt
Added Paths:
-----------
trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp
trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h
trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.cpp
trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.h
trunk/ktutorial/ktutorial-editor/tests/unit/serialization/DeserializationExceptionTest.cpp
trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialReaderTest.cpp
Modified: trunk/ktutorial/ktutorial-editor/CMakeLists.txt
===================================================================
--- trunk/ktutorial/ktutorial-editor/CMakeLists.txt 2010-03-26 01:10:24 UTC (rev 194)
+++ trunk/ktutorial/ktutorial-editor/CMakeLists.txt 2010-03-26 08:49:10 UTC (rev 195)
@@ -3,6 +3,7 @@
find_package(KDE4 REQUIRED)
include(KDE4Defaults)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}")
add_subdirectory(doc)
add_subdirectory(po)
Modified: trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt
===================================================================
--- trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt 2010-03-26 01:10:24 UTC (rev 194)
+++ trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt 2010-03-26 08:49:10 UTC (rev 195)
@@ -1,8 +1,10 @@
include_directories(${KDE4_INCLUDES})
set(ktutorial_editor_serialization_SRCS
+ DeserializationException.cpp
JavascriptExporter.cpp
Serialization.cpp
+ TutorialReader.cpp
TutorialWriter.cpp
)
Added: trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp
===================================================================
--- trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp (rev 0)
+++ trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp 2010-03-26 08:49:10 UTC (rev 195)
@@ -0,0 +1,33 @@
+/***************************************************************************
+ * Copyright (C) 2010 by Daniel Calviño Sánchez *
+ * dan...@gm... *
+ * *
+ * 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 <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#include "DeserializationException.h"
+
+//public:
+
+DeserializationException::DeserializationException(const QString& message):
+ std::exception(),
+ mMessage(message) {
+}
+
+DeserializationException::~DeserializationException() throw() {
+}
+
+const char* DeserializationException::what() const throw() {
+ return mMessage.toUtf8();
+}
Property changes on: trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp
___________________________________________________________________
Added: svn:eol-style
+ native
Added: trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h
===================================================================
--- trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h (rev 0)
+++ trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h 2010-03-26 08:49:10 UTC (rev 195)
@@ -0,0 +1,48 @@
+/***************************************************************************
+ * Copyright (C) 2010 by Daniel Calviño Sánchez *
+ * dan...@gm... *
+ * *
+ * 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 <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#ifndef DESERIALIZATIONEXCEPTION_H
+#define DESERIALIZATIONEXCEPTION_H
+
+#include <exception>
+#include <QString>
+
+/**
+ * Thrown when the XML can't be deserialized (for example, when it isn't well
+ * formed).
+ */
+class DeserializationException: public std::exception {
+public:
+
+ explicit DeserializationException(const QString& message = QString());
+ virtual ~DeserializationException() throw();
+
+ /**
+ * Returns the exception message.
+ *
+ * @return The exception message.
+ */
+ virtual const char* what() const throw();
+
+private:
+
+ QString mMessage;
+
+};
+
+#endif
Property changes on: trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h
___________________________________________________________________
Added: svn:eol-style
+ native
Added: trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.cpp
===================================================================
--- trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.cpp (rev 0)
+++ trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.cpp 2010-03-26 08:49:10 UTC (rev 195)
@@ -0,0 +1,242 @@
+/***************************************************************************
+ * Copyright (C) 2010 by Daniel Calviño Sánchez *
+ * dan...@gm... *
+ * *
+ * 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 <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#include "TutorialReader.h"
+
+#include <QDomDocument>
+
+#include "../Reaction.h"
+#include "../Step.h"
+#include "../Tutorial.h"
+#include "../WaitForComposed.h"
+#include "../WaitForEvent.h"
+#include "../WaitForNot.h"
+#include "../WaitForSignal.h"
+
+//public:
+
+TutorialReader::TutorialReader() {
+}
+
+Tutorial* TutorialReader::readTutorial(const QString& data)
+throw (DeserializationException) {
+ QDomDocument document;
+
+ QString errorMessage;
+ int errorLine;
+ int errorColumn;
+
+ if (!document.setContent(data, &errorMessage, &errorLine, &errorColumn) ||
+ document.documentElement().tagName() != "tutorial") {
+ throw DeserializationException(errorMessage);
+ }
+
+ return readTutorial(document.documentElement());
+}
+
+//private:
+
+Tutorial* TutorialReader::readTutorial(const QDomElement& element) {
+ Tutorial* tutorial = new Tutorial();
+
+ if (element.hasAttribute("name")) {
+ tutorial->setName(element.attribute("name"));
+ }
+
+ QDomElement childElement = element.firstChildElement();
+ while (!childElement.isNull()) {
+ if (childElement.tagName() == "description") {
+ tutorial->setDescription(childElement.text());
+ } else if (childElement.tagName() == "license") {
+ tutorial->setLicenseText(childElement.text());
+ } else if (childElement.tagName() == "setup") {
+ tutorial->setCustomSetupCode(childElement.text());
+ } else if (childElement.tagName() == "tearDown") {
+ tutorial->setCustomTearDownCode(childElement.text());
+ } else if (childElement.tagName() == "step") {
+ tutorial->addStep(readStep(childElement));
+ }
+
+ childElement = childElement.nextSiblingElement();
+ }
+
+ return tutorial;
+}
+
+Step* TutorialReader::readStep(const QDomElement& element) {
+ Step* step = new Step;
+
+ if (element.hasAttribute("id")) {
+ step->setId(element.attribute("id"));
+ }
+
+ QDomElement childElement = element.firstChildElement();
+ while (!childElement.isNull()) {
+ if (childElement.tagName() == "text") {
+ step->setText(childElement.text());
+ } else if (childElement.tagName() == "setup") {
+ step->setCustomSetupCode(childElement.text());
+ } else if (childElement.tagName() == "tearDown") {
+ step->setCustomTearDownCode(childElement.text());
+ } else if (childElement.tagName() == "reaction") {
+ step->addReaction(readReaction(childElement));
+ }
+
+ childElement = childElement.nextSiblingElement();
+ }
+
+ return step;
+}
+
+Reaction* TutorialReader::readReaction(const QDomElement& element) {
+ Reaction* reaction = new Reaction();
+
+ if (element.hasAttribute("triggerType")) {
+ Reaction::TriggerType triggerType = Reaction::OptionSelected;
+ if (element.attribute("triggerType") == "ConditionMet") {
+ triggerType = Reaction::ConditionMet;
+ }
+
+ reaction->setTriggerType(triggerType);
+ }
+
+ if (element.hasAttribute("responseType")) {
+ Reaction::ResponseType responseType = Reaction::NextStep;
+ if (element.attribute("responseType") == "CustomCode") {
+ responseType = Reaction::CustomCode;
+ }
+
+ reaction->setResponseType(responseType);
+ }
+
+ QDomElement childElement = element.firstChildElement();
+ while (!childElement.isNull()) {
+ if (childElement.tagName() == "option") {
+ if (childElement.hasAttribute("name")) {
+ reaction->setOptionName(childElement.attribute("name"));
+ }
+ } else if (isWaitForElement(childElement)) {
+ reaction->setWaitFor(readWaitFor(childElement));
+ } else if (childElement.tagName() == "customCode") {
+ reaction->setCustomCode(childElement.text());
+ } else if (childElement.tagName() == "nextStep") {
+ if (childElement.hasAttribute("id")) {
+ reaction->setNextStepId(childElement.attribute("id"));
+ }
+ }
+
+ childElement = childElement.nextSiblingElement();
+ }
+
+ return reaction;
+}
+
+WaitFor* TutorialReader::readWaitFor(const QDomElement& element) {
+ if (element.tagName() == "waitForComposed") {
+ return readWaitForComposed(element);
+ }
+ if (element.tagName() == "waitForEvent") {
+ return readWaitForEvent(element);
+ }
+ if (element.tagName() == "waitForNot") {
+ return readWaitForNot(element);
+ }
+ if (element.tagName() == "waitForSignal") {
+ return readWaitForSignal(element);
+ }
+
+ Q_ASSERT(false);
+ return 0;
+}
+
+WaitFor* TutorialReader::readWaitForComposed(const QDomElement& element) {
+ WaitForComposed* waitForComposed = new WaitForComposed();
+
+ if (element.hasAttribute("compositionType")) {
+ WaitForComposed::CompositionType compositionType = WaitForComposed::And;
+ if (element.attribute("compositionType") == "Or") {
+ compositionType = WaitForComposed::Or;
+ }
+
+ waitForComposed->setCompositionType(compositionType);
+ }
+
+ QDomElement childElement = element.firstChildElement();
+ while (!childElement.isNull()) {
+ if (isWaitForElement(childElement)) {
+ waitForComposed->addWaitFor(readWaitFor(childElement));
+ }
+
+ childElement = childElement.nextSiblingElement();
+ }
+
+ return waitForComposed;
+}
+
+WaitFor* TutorialReader::readWaitForEvent(const QDomElement& element) {
+ WaitForEvent* waitForEvent = new WaitForEvent();
+
+ if (element.hasAttribute("receiverName")) {
+ waitForEvent->setReceiverName(element.attribute("receiverName"));
+ }
+ if (element.hasAttribute("eventName")) {
+ waitForEvent->setEventName(element.attribute("eventName"));
+ }
+
+ return waitForEvent;
+}
+
+WaitFor* TutorialReader::readWaitForNot(const QDomElement& element) {
+ WaitForNot* waitForNot = new WaitForNot();
+
+ QDomElement childElement = element.firstChildElement();
+ while (!childElement.isNull()) {
+ if (isWaitForElement(childElement)) {
+ delete waitForNot->negatedWaitFor();
+ waitForNot->setNegatedWaitFor(readWaitFor(childElement));
+ }
+
+ childElement = childElement.nextSiblingElement();
+ }
+
+ return waitForNot;
+}
+
+WaitFor* TutorialReader::readWaitForSignal(const QDomElement& element) {
+ WaitForSignal* waitForSignal = new WaitForSignal();
+
+ if (element.hasAttribute("emitterName")) {
+ waitForSignal->setEmitterName(element.attribute("emitterName"));
+ }
+ if (element.hasAttribute("signalName")) {
+ waitForSignal->setSignalName(element.attribute("signalName"));
+ }
+
+ return waitForSignal;
+}
+
+bool TutorialReader::isWaitForElement(const QDomElement& element) {
+ if (element.tagName() != "waitForComposed" &&
+ element.tagName() != "waitForEvent" &&
+ element.tagName() != "waitForNot" &&
+ element.tagName() != "waitForSignal") {
+ return false;
+ }
+
+ return true;
+}
Property changes on: trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.cpp
___________________________________________________________________
Added: svn:eol-style
+ native
Added: trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.h
===================================================================
--- trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.h (rev 0)
+++ trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.h 2010-03-26 08:49:10 UTC (rev 195)
@@ -0,0 +1,147 @@
+/***************************************************************************
+ * Copyright (C) 2010 by Daniel Calviño Sánchez *
+ * dan...@gm... *
+ * *
+ * 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 <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#ifndef TUTORIALREADER_H
+#define TUTORIALREADER_H
+
+#include <QXmlStreamWriter>
+
+#include "DeserializationException.h"
+
+class QDomElement;
+class Reaction;
+class Step;
+class Tutorial;
+class WaitFor;
+class WaitForComposed;
+class WaitForEvent;
+class WaitForNot;
+class WaitForSignal;
+
+/**
+ * Deserializer for tutorials stored in XML.
+ * Creates a new Tutorial from the XML data generated by TutorialWriter. Anyway,
+ * if the XML data is not valid (see Tutorial.xsd for the W3C Schema), it
+ * ignores unknown attributes and elements, and uses those known to create the
+ * tutorial.
+ *
+ * @see TutorialWriter
+ */
+class TutorialReader {
+public:
+
+ /**
+ * Creates a new TutorialReader.
+ */
+ TutorialReader();
+
+ /**
+ * Returns the Tutorial stored in the given XML serialization.
+ * The tutorial must be deleted explicitly.
+ *
+ * If the XML is not well formed or its root element is not a "tutorial"
+ * element, a DeserializationException is thrown. In any other case, even if
+ * the XML is not valid, the deserializer tries to do its best: it ignores
+ * unknown attributes and elements and deserializes all the attributes and
+ * elements it knows.
+ *
+ * @param data The XML serialization.
+ * @return The Tutorial stored in the given XML serialization.
+ * @throw DeserializationException If there was a problem deserializing the
+ * tutorial.
+ */
+ Tutorial* readTutorial(const QString& data)
+ throw (DeserializationException);
+
+private:
+
+ /**
+ * Reads a new Tutorial from the "tutorial" XML element.
+ *
+ * @param element The element to read the Tutorial from.
+ * @return The new Tutorial.
+ */
+ Tutorial* readTutorial(const QDomElement& element);
+
+ /**
+ * Reads a new Step from the "step" XML element.
+ *
+ * @param element The element to read the Step from.
+ * @return The new Step.
+ */
+ Step* readStep(const QDomElement& element);
+
+ /**
+ * Reads a new Reaction from the "reaction" XML element.
+ *
+ * @param element The element to read the Reaction from.
+ * @return The new Reaction.
+ */
+ Reaction* readReaction(const QDomElement& element);
+
+ /**
+ * Returns a new WaitFor object from the appropriate subclass.
+ *
+ * @param element The element to read the WaitFor from.
+ * @return The new WaitFor.
+ */
+ WaitFor* readWaitFor(const QDomElement& element);
+
+ /**
+ * Reads a new WaitForComposed from the "waitForComposed" XML element.
+ *
+ * @param element The element to read the WaitForComposed from.
+ * @return The new WaitForComposed.
+ */
+ WaitFor* readWaitForComposed(const QDomElement& element);
+
+ /**
+ * Reads a new WaitForEvent from the "waitForEvent" XML element.
+ *
+ * @param element The element to read the WaitForEvent from.
+ * @return The new WaitForEvent.
+ */
+ WaitFor* readWaitForEvent(const QDomElement& element);
+
+ /**
+ * Reads a new WaitForNot from the "waitForNot" XML element.
+ *
+ * @param element The element to read the WaitForNot from.
+ * @return The new WaitForNot.
+ */
+ WaitFor* readWaitForNot(const QDomElement& element);
+
+ /**
+ * Reads a new WaitForSignal from the "waitForSignal" XML element.
+ *
+ * @param element The element to read the WaitForSignal from.
+ * @return The new WaitForSignal.
+ */
+ WaitFor* readWaitForSignal(const QDomElement& element);
+
+ /**
+ * Returns whether the given element is one of the WaitFor elements or not.
+ *
+ * @param element The element to check.
+ * @return Whether the given element is one of the WaitFor elements or not.
+ */
+ bool isWaitForElement(const QDomElement& element);
+
+};
+
+#endif
Property changes on: trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.h
___________________________________________________________________
Added: svn:eol-style
+ native
Modified: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt
===================================================================
--- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt 2010-03-26 01:10:24 UTC (rev 194)
+++ trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt 2010-03-26 08:49:10 UTC (rev 195)
@@ -12,6 +12,7 @@
ENDMACRO(UNIT_TESTS)
unit_tests(
+ DeserializationException
JavascriptExporter
Serialization
TutorialReader
@@ -25,6 +26,7 @@
ENDMACRO(MEM_TESTS)
mem_tests(
+ DeserializationException
JavascriptExporter
Serialization
TutorialReader
Added: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/DeserializationExceptionTest.cpp
===================================================================
--- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/DeserializationExceptionTest.cpp (rev 0)
+++ trunk/ktutorial/ktutorial-editor/tests/unit/serialization/DeserializationExceptionTest.cpp 2010-03-26 08:49:10 UTC (rev 195)
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * Copyright (C) 2010 by Daniel Calviño Sánchez *
+ * dan...@gm... *
+ * *
+ * 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 <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#include <QtTest>
+
+#include "DeserializationException.h"
+
+class DeserializationExceptionTest: public QObject {
+Q_OBJECT
+
+private slots:
+
+ void testConstructor();
+ void testConstructorEmpty();
+
+};
+
+void DeserializationExceptionTest::testConstructor() {
+ DeserializationException exception(QString("The message"));
+
+ QCOMPARE(exception.what(), "The message");
+}
+
+void DeserializationExceptionTest::testConstructorEmpty() {
+ DeserializationException exception;
+
+ QCOMPARE(exception.what(), "");
+}
+
+QTEST_MAIN(DeserializationExceptionTest)
+
+#include "DeserializationExceptionTest.moc"
Property changes on: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/DeserializationExceptionTest.cpp
___________________________________________________________________
Added: svn:eol-style
+ native
Added: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialReaderTest.cpp
===================================================================
--- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialReaderTest.cpp (rev 0)
+++ trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialReaderTest.cpp 2010-03-26 08:49:10 UTC (rev 195)
@@ -0,0 +1,658 @@
+/***************************************************************************
+ * Copyright (C) 2010 by Daniel Calviño Sánchez *
+ * dan...@gm... *
+ * *
+ * 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 <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#include <QtTest>
+
+#include "TutorialReader.h"
+
+#include "../Reaction.h"
+#include "../Step.h"
+#include "../Tutorial.h"
+#include "../WaitForComposed.h"
+#include "../WaitForEvent.h"
+#include "../WaitForNot.h"
+#include "../WaitForSignal.h"
+
+#define HEADER_XML \
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+
+#define TUTORIAL_ELEMENTS \
+" <description>The description,\nwith < and >\n</description>\n" \
+" <license>The license text,\nwith < and >\n</license>\n" \
+" <setup>The setup code,\nwith < and >\n</setup>\n" \
+" <tearDown>The tear down code,\nwith < and >\n</tearDown>\n"
+
+#define STEP_PARENT_START \
+HEADER_XML \
+"<tutorial>\n"
+
+#define STEP_PARENT_END \
+"</tutorial>\n"
+
+#define STEP_ELEMENTS \
+" <text>The text,\nwith < and >\n</text>\n" \
+" <setup>The setup code,\nwith < and >\n</setup>\n" \
+" <tearDown>The tear down code,\nwith < and >\n</tearDown>\n"
+
+#define REACTION_PARENT_START \
+STEP_PARENT_START \
+" <step>\n"
+
+#define REACTION_PARENT_END \
+" </step>\n" \
+STEP_PARENT_END
+
+#define WAITFOR_PARENT_START \
+REACTION_PARENT_START \
+" <reaction triggerType=\"ConditionMet\" responseType=\"NextStep\">\n"
+
+#define WAITFOR_PARENT_END \
+" </reaction>\n" \
+REACTION_PARENT_END
+
+class TutorialReaderTest: public QObject {
+Q_OBJECT
+
+private slots:
+
+ void testTutorial();
+ void testTutorialEmpty();
+ void testTutorialWithSeveralSteps();
+
+ void testStep();
+ void testStepEmpty();
+ void testStepWithSeveralReactions();
+
+ void testReactionConditionCustomCode();
+ void testReactionOptionNextStep();
+ void testReactionEmpty();
+
+ void testWaitForEvent();
+ void testWaitForEventEmpty();
+ void testWaitForSignal();
+ void testWaitForSignalEmpty();
+ void testWaitForComposed();
+ void testWaitForComposedEmpty();
+ void testWaitForNot();
+ void testWaitForNotWithoutNegatedWaitFor();
+
+ void testXmlNotWellFormed();
+ void testXmlWithoutRootTutorialElement();
+ void testXmlWithGarbageElementsAndAttributes();
+
+private:
+
+ void assertWaitForSignal(WaitFor* waitFor, const QString& emitterName,
+ const QString& signalName) const;
+
+ QString addGarbageToXmlData(const QString& data) const;
+
+};
+
+void TutorialReaderTest::testTutorial() {
+ QString data =
+HEADER_XML
+"<tutorial name=\"The "name"\">\n"
+" <description>The description,\nwith < and >\n</description>\n"
+" <license>The license text,\nwith < and >\n</license>\n"
+" <setup>The setup code,\nwith < and >\n</setup>\n"
+" <tearDown>The tear down code,\nwith < and >\n</tearDown>\n"
+"</tutorial>\n";
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+
+ QVERIFY(tutorial);
+ QCOMPARE(tutorial->name(), QString("The \"name\""));
+ QCOMPARE(tutorial->description(),
+ QString("The description,\nwith < and >\n"));
+ QCOMPARE(tutorial->licenseText(),
+ QString("The license text,\nwith < and >\n"));
+ QCOMPARE(tutorial->customSetupCode(),
+ QString("The setup code,\nwith < and >\n"));
+ QCOMPARE(tutorial->customTearDownCode(),
+ QString("The tear down code,\nwith < and >\n"));
+ QCOMPARE(tutorial->steps().count(), 0);
+}
+
+void TutorialReaderTest::testTutorialEmpty() {
+ QString data =
+HEADER_XML
+"<tutorial/>\n";
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+
+ QVERIFY(tutorial);
+ QCOMPARE(tutorial->name(), QString(""));
+ QCOMPARE(tutorial->description(), QString(""));
+ QCOMPARE(tutorial->licenseText(), QString(""));
+ QCOMPARE(tutorial->customSetupCode(), QString(""));
+ QCOMPARE(tutorial->customTearDownCode(), QString(""));
+ QCOMPARE(tutorial->steps().count(), 0);
+}
+
+void TutorialReaderTest::testTutorialWithSeveralSteps() {
+ QString data =
+HEADER_XML
+"<tutorial name=\"The "name"\">\n"
+TUTORIAL_ELEMENTS
+" <step id=\"The id1\">\n"
+" <text>The text1</text>\n"
+" </step>\n"
+" <step id=\"The id2\">\n"
+" <text>The text2</text>\n"
+" </step>\n"
+"</tutorial>\n";
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+
+ QVERIFY(tutorial);
+ QCOMPARE(tutorial->name(), QString("The \"name\""));
+ QCOMPARE(tutorial->description(),
+ QString("The description,\nwith < and >\n"));
+ QCOMPARE(tutorial->licenseText(),
+ QString("The license text,\nwith < and >\n"));
+ QCOMPARE(tutorial->customSetupCode(),
+ QString("The setup code,\nwith < and >\n"));
+ QCOMPARE(tutorial->customTearDownCode(),
+ QString("The tear down code,\nwith < and >\n"));
+ QCOMPARE(tutorial->steps().count(), 2);
+ Step* step = tutorial->steps()[0];
+ QVERIFY(step);
+ QCOMPARE(step->id(), QString("The id1"));
+ QCOMPARE(step->text(), QString("The text1"));
+ step = tutorial->steps()[1];
+ QVERIFY(step);
+ QCOMPARE(step->id(), QString("The id2"));
+ QCOMPARE(step->text(), QString("The text2"));
+}
+
+void TutorialReaderTest::testStep() {
+ QString data =
+STEP_PARENT_START
+" <step id=\"The "id"\">\n"
+" <text>The text,\nwith < and >\n</text>\n"
+" <setup>The setup code,\nwith < and >\n</setup>\n"
+" <tearDown>The tear down code,\nwith < and >\n</tearDown>\n"
+" </step>\n"
+STEP_PARENT_END;
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+ Step* step = tutorial->steps()[0];
+
+ QVERIFY(step);
+ QCOMPARE(step->id(), QString("The \"id\""));
+ QCOMPARE(step->text(), QString("The text,\nwith < and >\n"));
+ QCOMPARE(step->customSetupCode(),
+ QString("The setup code,\nwith < and >\n"));
+ QCOMPARE(step->customTearDownCode(),
+ QString("The tear down code,\nwith < and >\n"));
+ QCOMPARE(step->reactions().count(), 0);
+}
+
+void TutorialReaderTest::testStepEmpty() {
+ QString data =
+STEP_PARENT_START
+" <step/>\n"
+STEP_PARENT_END;
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+ Step* step = tutorial->steps()[0];
+
+ QVERIFY(step);
+ QCOMPARE(step->id(), QString(""));
+ QCOMPARE(step->text(), QString(""));
+ QCOMPARE(step->customSetupCode(), QString(""));
+ QCOMPARE(step->customTearDownCode(), QString(""));
+ QCOMPARE(step->reactions().count(), 0);
+}
+
+void TutorialReaderTest::testStepWithSeveralReactions() {
+ QString data =
+STEP_PARENT_START
+" <step id=\"The "id"\">\n"
+STEP_ELEMENTS
+" <reaction triggerType=\"ConditionMet\" responseType=\"CustomCode\"/>\n"
+" <reaction triggerType=\"OptionSelected\" responseType=\"NextStep\">\n"
+" <option name=\"The option name\"/>\n"
+" <nextStep id=\"Another id\"/>\n"
+" </reaction>\n"
+" </step>\n"
+STEP_PARENT_END;
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+ Step* step = tutorial->steps()[0];
+
+ QVERIFY(step);
+ QCOMPARE(step->id(), QString("The \"id\""));
+ QCOMPARE(step->text(), QString("The text,\nwith < and >\n"));
+ QCOMPARE(step->customSetupCode(),
+ QString("The setup code,\nwith < and >\n"));
+ QCOMPARE(step->customTearDownCode(),
+ QString("The tear down code,\nwith < and >\n"));
+ QCOMPARE(step->reactions().count(), 2);
+ Reaction* reaction = step->reactions()[0];
+ QVERIFY(reaction);
+ QCOMPARE(reaction->triggerType(), Reaction::ConditionMet);
+ QCOMPARE(reaction->responseType(), Reaction::CustomCode);
+ reaction = step->reactions()[1];
+ QVERIFY(reaction);
+ QCOMPARE(reaction->triggerType(), Reaction::OptionSelected);
+ QCOMPARE(reaction->optionName(), QString("The option name"));
+ QCOMPARE(reaction->responseType(), Reaction::NextStep);
+ QCOMPARE(reaction->nextStepId(), QString("Another id"));
+}
+
+void TutorialReaderTest::testReactionConditionCustomCode() {
+ QString data =
+REACTION_PARENT_START
+" <reaction triggerType=\"ConditionMet\" responseType=\"CustomCode\">\n"
+" <option name=\"The "option" name\"/>\n"
+" <waitForSignal emitterName=\"The emitter name\" \
+signalName=\"theSignalName(Argument1Type, Argument2Type)\"/>\n"
+" <customCode>The custom code,\nwith < and >\n</customCode>\n"
+" <nextStep id=\"Another "id"\"/>\n"
+" </reaction>\n"
+REACTION_PARENT_END;
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+ Reaction* reaction = tutorial->steps()[0]->reactions()[0];
+
+ QVERIFY(reaction);
+ QCOMPARE(reaction->triggerType(), Reaction::ConditionMet);
+ QCOMPARE(reaction->optionName(), QString("The \"option\" name"));
+ assertWaitForSignal(reaction->waitFor(), "The emitter name",
+ "theSignalName(Argument1Type, Argument2Type)");
+ QCOMPARE(reaction->responseType(), Reaction::CustomCode);
+ QCOMPARE(reaction->customCode(),
+ QString("The custom code,\nwith < and >\n"));
+ QCOMPARE(reaction->nextStepId(), QString("Another \"id\""));
+}
+
+void TutorialReaderTest::testReactionOptionNextStep() {
+ QString data =
+REACTION_PARENT_START
+" <reaction triggerType=\"OptionSelected\" responseType=\"NextStep\">\n"
+" <option name=\"The "option" name\"/>\n"
+" <waitForSignal emitterName=\"The emitter name\" \
+signalName=\"theSignalName(Argument1Type, Argument2Type)\"/>\n"
+" <customCode>The custom code,\nwith < and >\n</customCode>\n"
+" <nextStep id=\"Another "id"\"/>\n"
+" </reaction>\n"
+REACTION_PARENT_END;
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+ Reaction* reaction = tutorial->steps()[0]->reactions()[0];
+
+ QVERIFY(reaction);
+ QCOMPARE(reaction->triggerType(), Reaction::OptionSelected);
+ QCOMPARE(reaction->optionName(), QString("The \"option\" name"));
+ assertWaitForSignal(reaction->waitFor(), "The emitter name",
+ "theSignalName(Argument1Type, Argument2Type)");
+ QCOMPARE(reaction->responseType(), Reaction::NextStep);
+ QCOMPARE(reaction->customCode(),
+ QString("The custom code,\nwith < and >\n"));
+ QCOMPARE(reaction->nextStepId(), QString("Another \"id\""));
+}
+
+void TutorialReaderTest::testReactionEmpty() {
+ QString data =
+REACTION_PARENT_START
+" <reaction triggerType=\"ConditionMet\" responseType=\"CustomCode\"/>\n"
+REACTION_PARENT_END;
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+ Reaction* reaction = tutorial->steps()[0]->reactions()[0];
+
+ QVERIFY(reaction);
+ QCOMPARE(reaction->triggerType(), Reaction::ConditionMet);
+ QCOMPARE(reaction->optionName(), QString(""));
+ QCOMPARE(reaction->waitFor(), (WaitFor*)0);
+ QCOMPARE(reaction->responseType(), Reaction::CustomCode);
+ QCOMPARE(reaction->customCode(), QString(""));
+ QCOMPARE(reaction->nextStepId(), QString(""));
+}
+
+void TutorialReaderTest::testWaitForEvent() {
+ QString data =
+WAITFOR_PARENT_START
+" <waitForEvent receiverName=\"The "receiver" name\" \
+eventName=\"The"Event"Name\"/>\n"
+WAITFOR_PARENT_END;
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+ WaitFor* waitFor = tutorial->steps()[0]->reactions()[0]->waitFor();
+
+ WaitForEvent* waitForEvent = qobject_cast<WaitForEvent*>(waitFor);
+ QVERIFY(waitForEvent);
+ QCOMPARE(waitForEvent->receiverName(), QString("The \"receiver\" name"));
+ QCOMPARE(waitForEvent->eventName(), QString("The\"Event\"Name"));
+}
+
+void TutorialReaderTest::testWaitForEventEmpty() {
+ QString data =
+WAITFOR_PARENT_START
+" <waitForEvent/>\n"
+WAITFOR_PARENT_END;
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+ WaitFor* waitFor = tutorial->steps()[0]->reactions()[0]->waitFor();
+
+ WaitForEvent* waitForEvent = qobject_cast<WaitForEvent*>(waitFor);
+ QVERIFY(waitForEvent);
+ QCOMPARE(waitForEvent->receiverName(), QString(""));
+ QCOMPARE(waitForEvent->eventName(), QString(""));
+}
+
+void TutorialReaderTest::testWaitForSignal() {
+ QString data =
+WAITFOR_PARENT_START
+" <waitForSignal emitterName=\"The "emitter" name\" \
+signalName=\"theSignalName("Argument1Type")\"/>\n"
+WAITFOR_PARENT_END;
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+ WaitFor* waitFor = tutorial->steps()[0]->reactions()[0]->waitFor();
+
+ assertWaitForSignal(waitFor, "The \"emitter\" name",
+ "theSignalName(\"Argument1Type\")");
+}
+
+void TutorialReaderTest::testWaitForSignalEmpty() {
+ QString data =
+WAITFOR_PARENT_START
+" <waitForSignal/>\n"
+WAITFOR_PARENT_END;
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+ WaitFor* waitFor = tutorial->steps()[0]->reactions()[0]->waitFor();
+
+ assertWaitForSignal(waitFor, "", "");
+}
+
+void TutorialReaderTest::testWaitForComposed() {
+ QString data =
+WAITFOR_PARENT_START
+" <waitForComposed compositionType=\"And\">\n"
+" <waitForSignal emitterName=\"The emitter name1\" \
+signalName=\"theSignalName1()\"/>\n"
+" <waitForComposed compositionType=\"Or\">\n"
+" <waitForSignal emitterName=\"The emitter name2\" \
+signalName=\"theSignalName2()\"/>\n"
+" <waitForSignal emitterName=\"The emitter name3\" \
+signalName=\"theSignalName3()\"/>\n"
+" </waitForComposed>\n"
+" </waitForComposed>\n"
+WAITFOR_PARENT_END;
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+ WaitFor* waitFor = tutorial->steps()[0]->reactions()[0]->waitFor();
+
+ WaitForComposed* waitForAnd = qobject_cast<WaitForComposed*>(waitFor);
+ QVERIFY(waitForAnd);
+ QCOMPARE(waitForAnd->compositionType(), WaitForComposed::And);
+ QCOMPARE(waitForAnd->waitFors().count(), 2);
+ assertWaitForSignal(waitForAnd->waitFors()[0], "The emitter name1",
+ "theSignalName1()");
+
+ WaitForComposed* waitForOr =
+ qobject_cast<WaitForComposed*>(waitForAnd->waitFors()[1]);
+ QVERIFY(waitForOr);
+ QCOMPARE(waitForOr->compositionType(), WaitForComposed::Or);
+ QCOMPARE(waitForOr->waitFors().count(), 2);
+ assertWaitForSignal(waitForOr->waitFors()[0], "The emitter name2",
+ "theSignalName2()");
+ assertWaitForSignal(waitForOr->waitFors()[1], "The emitter name3",
+ "theSignalName3()");
+}
+
+void TutorialReaderTest::testWaitForComposedEmpty() {
+ QString data =
+WAITFOR_PARENT_START
+" <waitForComposed compositionType=\"And\">\n"
+" <waitForComposed compositionType=\"And\"/>\n"
+" <waitForComposed compositionType=\"Or\"/>\n"
+" </waitForComposed>\n"
+WAITFOR_PARENT_END;
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+ WaitFor* waitFor = tutorial->steps()[0]->reactions()[0]->waitFor();
+
+ WaitForComposed* waitForAnd = qobject_cast<WaitForComposed*>(waitFor);
+ QVERIFY(waitForAnd);
+ QCOMPARE(waitForAnd->compositionType(), WaitForComposed::And);
+ QCOMPARE(waitForAnd->waitFors().count(), 2);
+
+ WaitForComposed* waitForAndChild =
+ qobject_cast<WaitForComposed*>(waitForAnd->waitFors()[0]);
+ QVERIFY(waitForAndChild);
+ QCOMPARE(waitForAndChild->compositionType(), WaitForComposed::And);
+ QCOMPARE(waitForAndChild->waitFors().count(), 0);
+
+ WaitForComposed* waitForOrChild =
+ qobject_cast<WaitForComposed*>(waitForAnd->waitFors()[1]);
+ QVERIFY(waitForOrChild);
+ QCOMPARE(waitForOrChild->compositionType(), WaitForComposed::Or);
+ QCOMPARE(waitForOrChild->waitFors().count(), 0);
+}
+
+void TutorialReaderTest::testWaitForNot() {
+ QString data =
+WAITFOR_PARENT_START
+" <waitForNot>\n"
+" <waitForSignal emitterName=\"The emitter name\" \
+signalName=\"theSignalName()\"/>\n"
+" </waitForNot>\n"
+WAITFOR_PARENT_END;
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+ WaitFor* waitFor = tutorial->steps()[0]->reactions()[0]->waitFor();
+
+ WaitForNot* waitForNot = qobject_cast<WaitForNot*>(waitFor);
+ QVERIFY(waitForNot);
+ WaitForSignal* waitForSignal =
+ qobject_cast<WaitForSignal*>(waitForNot->negatedWaitFor());
+ QVERIFY(waitForSignal);
+ QCOMPARE(waitForSignal->emitterName(), QString("The emitter name"));
+ QCOMPARE(waitForSignal->signalName(), QString("theSignalName()"));
+}
+
+void TutorialReaderTest::testWaitForNotWithoutNegatedWaitFor() {
+ QString data =
+WAITFOR_PARENT_START
+" <waitForNot/>\n"
+WAITFOR_PARENT_END;
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+ WaitFor* waitFor = tutorial->steps()[0]->reactions()[0]->waitFor();
+
+ WaitForNot* waitForNot = qobject_cast<WaitForNot*>(waitFor);
+ QVERIFY(waitForNot);
+ QCOMPARE(waitForNot->negatedWaitFor(), (WaitFor*)0);
+}
+
+void TutorialReaderTest::testXmlNotWellFormed() {
+ QString data =
+HEADER_XML
+"<tutorial>\n"
+" <step>\n"
+" </invalidEndElement>\n"
+"</tutorial>\n";
+
+ TutorialReader reader;
+ try {
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+ QFAIL("Expected DeserializationException not thrown");
+ } catch (DeserializationException e) {
+ }
+}
+
+void TutorialReaderTest::testXmlWithoutRootTutorialElement() {
+ QString data =
+HEADER_XML
+"<unknownRootElement>\n"
+"</unknownRootElement>\n";
+
+ TutorialReader reader;
+ try {
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+ QFAIL("Expected DeserializationException not thrown");
+ } catch (DeserializationException e) {
+ }
+}
+
+void TutorialReaderTest::testXmlWithGarbageElementsAndAttributes() {
+ QString data =
+HEADER_XML
+"<tutorial name=\"The "name"\">\n"
+TUTORIAL_ELEMENTS
+" <step id=\"The id1\">\n"
+STEP_ELEMENTS
+" </step>\n"
+" <step id=\"The id2\">\n"
+" <text>The text2</text>\n"
+" <reaction triggerType=\"OptionSelected\" responseType=\"NextStep\">\n"
+" <option name=\"The "option" name\"/>\n"
+" <customCode>The custom code,\nwith < and >\n</customCode>\n"
+" <nextStep id=\"Another "id"\"/>\n"
+" </reaction>\n"
+" <reaction triggerType=\"ConditionMet\" responseType=\"CustomCode\">\n"
+" <waitForComposed compositionType=\"And\">\n"
+" <waitForSignal emitterName=\"The emitter name1\" \
+signalName=\"theSignalName1()\"/>\n"
+" <waitForComposed compositionType=\"Or\">\n"
+" <waitForSignal emitterName=\"The emitter name2\" \
+signalName=\"theSignalName2()\"/>\n"
+" <waitForSignal emitterName=\"The emitter name3\" \
+signalName=\"theSignalName3()\"/>\n"
+" </waitForComposed>\n"
+" </waitForComposed>\n"
+" </reaction>\n"
+" </step>\n"
+"</tutorial>\n";
+
+ data = addGarbageToXmlData(data);
+
+ TutorialReader reader;
+ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data));
+
+ QVERIFY(tutorial);
+ QCOMPARE(tutorial->name(), QString("The \"name\""));
+ QCOMPARE(tutorial->description(),
+ QString("The description,\nwith < and >\n"));
+ QCOMPARE(tutorial->licenseText(),
+ QString("The license text,\nwith < and >\n"));
+ QCOMPARE(tutorial->customSetupCode(),
+ QString("The setup code,\nwith < and >\n"));
+ QCOMPARE(tutorial->customTearDownCode(),
+ QString("The tear down code,\nwith < and >\n"));
+ QCOMPARE(tutorial->steps().count(), 2);
+
+ Step* step = tutorial->steps()[0];
+ QVERIFY(step);
+ QCOMPARE(step->id(), QString("The id1"));
+ QCOMPARE(step->text(), QString("The text,\nwith < and >\n"));
+ QCOMPARE(step->customSetupCode(),
+ QString("The setup code,\nwith < and >\n"));
+ QCOMPARE(step->customTearDownCode(),
+ QString("The tear down code,\nwith < and >\n"));
+ QCOMPARE(step->reactions().count(), 0);
+
+ step = tutorial->steps()[1];
+ QVERIFY(step);
+ QCOMPARE(step->id(), QString("The id2"));
+ QCOMPARE(step->text(), QString("The text2"));
+ QCOMPARE(step->reactions().count(), 2);
+
+ Reaction* reaction = step->reactions()[0];
+ QCOMPARE(reaction->triggerType(), Reaction::OptionSelected);
+ QCOMPARE(reaction->optionName(), QString("The \"option\" name"));
+ QCOMPARE(reaction->waitFor(), (WaitFor*)0);
+ QCOMPARE(reaction->responseType(), Reaction::NextStep);
+ QCOMPARE(reaction->customCode(),
+ QString("The custom code,\nwith < and >\n"));
+ QCOMPARE(reaction->nextStepId(), QString("Another \"id\""));
+
+ reaction = step->reactions()[1];
+ QCOMPARE(reaction->triggerType(), Reaction::ConditionMet);
+ QCOMPARE(reaction->optionName(), QString(""));
+ QCOMPARE(reaction->responseType(), Reaction::CustomCode);
+ QCOMPARE(reaction->customCode(), QString(""));
+ QCOMPARE(reaction->nextStepId(), QString(""));
+ WaitFor* waitFor = reaction->waitFor();
+
+ WaitForComposed* waitForAnd = qobject_cast<WaitForComposed*>(waitFor);
+ QVERIFY(waitForAnd);
+ QCOMPARE(waitForAnd->compositionType(), WaitForComposed::And);
+ QCOMPARE(waitForAnd->waitFors().count(), 2);
+ assertWaitForSignal(waitForAnd->waitFors()[0], "The emitter name1",
+ "theSignalName1()");
+
+ WaitForComposed* waitForOr =
+ qobject_cast<WaitForComposed*>(waitForAnd->waitFors()[1]);
+ QVERIFY(waitForOr);
+ QCOMPARE(waitForOr->compositionType(), WaitForComposed::Or);
+ QCOMPARE(waitForOr->waitFors().count(), 2);
+ assertWaitForSignal(waitForOr->waitFors()[0], "The emitter name2",
+ "theSignalName2()");
+ assertWaitForSignal(waitForOr->waitFors()[1], "The emitter name3",
+ "theSignalName3()");
+}
+
+/////////////////////////////////// Helpers ////////////////////////////////////
+
+void TutorialReaderTest::assertWaitForSignal(WaitFor* waitFor,
+ const QString& emitterName,
+ const QString& signalName) const {
+ WaitForSignal* waitForSignal = qobject_cast<WaitForSignal*>(waitFor);
+ QVERIFY(waitForSignal);
+ QCOMPARE(waitForSignal->emitterName(), emitterName);
+ QCOMPARE(waitForSignal->signalName(), signalName);
+}
+
+QString TutorialReaderTest::addGarbageToXmlData(const QString& data) const {
+ QString garbagedData = data;
+ //Add a " garbage=\"trash\"" attribute to every element
+ garbagedData.replace(QRegExp("(<\\w+( \\w+=\"[ &;\"\\w]*\")*)(>|/>)"),
+ "\\1 garbage=\"trash\"\\3");
+ //Add a "<garbage/>" element after each start element (even for text
+ //elements)
+ garbagedData.replace(QRegExp("(<\\w+( \\w+=\"[ &;\"\\w]*\")*>)"),
+ "\\1<garbage/>");
+ return garbagedData;
+}
+
+QTEST_MAIN(TutorialReaderTest)
+
+#include "TutorialReaderTest.moc"
Property changes on: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialReaderTest.cpp
___________________________________________________________________
Added: svn:eol-style
+ native
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|