From 7c779099b3acd1fa969dde718299484ebe0d2775 Mon Sep 17 00:00:00 2001 From: Stefan Radomski Date: Sun, 10 Feb 2013 20:50:07 +0100 Subject: Various bug fixes --- src/uscxml/Interpreter.cpp | 297 +++++++++++++++++++-- src/uscxml/Interpreter.h | 5 +- .../concurrency/eventqueue/DelayedEventQueue.h | 4 + test/run-scxml-test-framework.sh | 102 +++---- .../test/history/history0.json | 6 +- .../test/send-data/send1.scxml | 4 +- test/src/scxml-test-framework-client.cpp | 16 +- 7 files changed, 346 insertions(+), 88 deletions(-) diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index 5b947a7..4f1f31f 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -303,6 +303,7 @@ void Interpreter::interpret() { } enterStates(initialTransitions); +// assert(hasLegalConfiguration()); mainEventLoop(); // set datamodel to null from this thread @@ -473,10 +474,15 @@ void Interpreter::mainEventLoop() { if (!_internalQueue.empty()) continue; + // assume that we have a legal configuration as soon as the internal queue is empty + assert(hasLegalConfiguration()); + monIter = _monitors.begin(); - while(monIter != _monitors.end()) { - (*monIter)->onStableConfiguration(this); - monIter++; + if (!_sendQueue || _sendQueue->isEmpty()) { + while(monIter != _monitors.end()) { + (*monIter)->onStableConfiguration(this); + monIter++; + } } // whenever we have a stable configuration, run the mainThread hooks with 200fps @@ -674,7 +680,9 @@ void Interpreter::send(const Arabica::DOM::Node& element) { if (HAS_ATTR(element, "namelist")) { std::vector names = tokenizeIdRefs(ATTR(element, "namelist")); for (int i = 0; i < names.size(); i++) { - sendReq.namelist[names[i]] = _dataModel.evalAsString(names[i]); + std::string namelistValue = _dataModel.evalAsString(names[i]); + sendReq.namelist[names[i]] = namelistValue; + sendReq.compound[names[i]] = Data(namelistValue, Data::VERBATIM); } } @@ -697,6 +705,7 @@ void Interpreter::send(const Arabica::DOM::Node& element) { std::string paramKey = ATTR(params[i], "name"); boost::algorithm::to_lower(paramKey); sendReq.params.insert(std::make_pair(paramKey, paramValue)); + sendReq.compound[paramKey] = Data(paramValue, Data::VERBATIM); } // content @@ -706,12 +715,17 @@ void Interpreter::send(const Arabica::DOM::Node& element) { if (contents.size() > 0) { if (HAS_ATTR(contents[0], "expr")) { if (_dataModel) { - sendReq.content = _dataModel.evalAsString(ATTR(contents[0], "expr")); + std::string contentValue = _dataModel.evalAsString(ATTR(contents[0], "expr")); + sendReq.content = contentValue; + sendReq.atom = contentValue; + sendReq.type = Data::VERBATIM; } else { LOG(ERROR) << "content element has expr attribute but no datamodel is specified."; } } else if (contents[0].hasChildNodes()) { sendReq.content = contents[0].getFirstChild().getNodeValue(); + sendReq.atom = sendReq.content; + sendReq.type = Data::VERBATIM; } else { LOG(ERROR) << "content element does not specify any content."; } @@ -743,6 +757,8 @@ void Interpreter::delayedSend(void* userdata, std::string eventName) { } else { LOG(ERROR) << "Can not send to parent, we were not invoked" << std::endl; } + } else if (boost::iequals(sendReq.target, "#_internal")) { + INSTANCE->_internalQueue.push_back(sendReq); } else if (sendReq.target.find_first_of("#_") == 0) { // send to invoker std::string invokeId = sendReq.target.substr(2, sendReq.target.length() - 2); @@ -912,9 +928,13 @@ Arabica::XPath::NodeSet Interpreter::selectTransitions(const std::s for (unsigned int i = 0; i < atomicStates.size(); i++) { NodeSet ancestors = getProperAncestors(atomicStates[i], Arabica::DOM::Node()); - ancestors.push_back(atomicStates[i]); - for (unsigned int j = 0; j < ancestors.size(); j++) { - NodeSet transitions = filterChildElements(_xmlNSPrefix + "transition", ancestors[j]); + + NodeSet sortedAncestors; + sortedAncestors.push_back(atomicStates[i]); + sortedAncestors.insert(sortedAncestors.end(), ancestors.begin(), ancestors.end()); + + for (unsigned int j = 0; j < sortedAncestors.size(); j++) { + NodeSet transitions = filterChildElements(_xmlNSPrefix + "transition", sortedAncestors[j]); for (unsigned int k = 0; k < transitions.size(); k++) { if (((Arabica::DOM::Element)transitions[k]).hasAttribute("event") && nameMatch(((Arabica::DOM::Element)transitions[k]).getAttribute("event"), event) && @@ -927,6 +947,8 @@ Arabica::XPath::NodeSet Interpreter::selectTransitions(const std::s LOOP: ; } + + enabledTransitions = filterPreempted(enabledTransitions); return enabledTransitions; } @@ -1029,8 +1051,12 @@ Arabica::XPath::NodeSet Interpreter::filterPreempted(const Arabica: Arabica::DOM::Node t = enabledTransitions[i]; for (unsigned int j = i+1; j < enabledTransitions.size(); j++) { Arabica::DOM::Node t2 = enabledTransitions[j]; - if (isPreemptingTransition(t2, t)) + if (isPreemptingTransition(t2, t)) { +#if 0 + std::cout << "Preempting transitions: " << std::endl << t2 << std::endl << t; +#endif goto LOOP; + } } filteredTransitions.push_back(t); LOOP: @@ -1042,6 +1068,12 @@ LOOP: bool Interpreter::isPreemptingTransition(const Arabica::DOM::Node& t1, const Arabica::DOM::Node& t2) { assert(t1); assert(t2); + +#if 0 + std::cout << "Checking preemption: " << std::endl << t1 << std::endl << t2 << std::endl; +#endif + +#if 1 if (t1 == t2) return false; if (isWithinSameChild(t1) && (!isTargetless(t2) && !isWithinSameChild(t2))) @@ -1049,8 +1081,49 @@ bool Interpreter::isPreemptingTransition(const Arabica::DOM::Node& if (!isTargetless(t1) && !isWithinSameChild(t1)) return true; return false; +#endif + +#if 0 + // isPreempted from chris nuernberger + if (isTargetless(t1)) + return false; + + Arabica::DOM::Node existingRoot = getTransitionSubgraph(t1); + Arabica::DOM::Node nextRoot = getTransitionSubgraph(t2); + + if (existingRoot == nextRoot || isDescendant(existingRoot, nextRoot) || isDescendant(nextRoot, existingRoot)) + return true; + + return false; +#endif } +/** + * filterPreempted approach from chris nuernberger + */ +Arabica::DOM::Node Interpreter::getTransitionSubgraph(const Arabica::DOM::Node& transition) { + Arabica::XPath::NodeSet targets = getTargetStates(transition); + Arabica::DOM::Node source = getSourceState(transition); + + if (!targets.size() == 0) + return source; + + if (boost::iequals(ATTR(transition, "type"), "internal") && isCompound(source)) { + bool allDescendants = true; + for (int i = 0; i < targets.size(); i++) { + if (!isDescendant(targets[i], source)) { + allDescendants = false; + break; + } + } + if (allDescendants) + return source; + } + + targets.push_back(source); + return findLCCA(targets); +} + void Interpreter::microstep(const Arabica::XPath::NodeSet& enabledTransitions) { #if 0 std::cout << "Transitions: "; @@ -1119,6 +1192,10 @@ void Interpreter::executeContent(const Arabica::DOM::Node& content) } else if (boost::iequals(TAGNAME(content), _xmlNSPrefix + "if")) { // --- IF / ELSEIF / ELSE -------------- Arabica::DOM::Element ifElem = (Arabica::DOM::Element)content; +#if 0 + if (HAS_ATTR(ifElem, "cond")) + std::cout << ATTR(ifElem, "cond") << std::endl; +#endif if(hasConditionMatch(ifElem)) { // condition is true, execute all content up to an elseif, else or end if (ifElem.hasChildNodes()) { @@ -1126,7 +1203,7 @@ void Interpreter::executeContent(const Arabica::DOM::Node& content) for (unsigned int i = 0; i < childs.getLength(); i++) { if (childs.item(i).getNodeType() != Node_base::ELEMENT_NODE) continue; - if (boost::iequals(TAGNAME(childs.item(i)), _xmlNSPrefix + "elsif") || + if (boost::iequals(TAGNAME(childs.item(i)), _xmlNSPrefix + "elseif") || boost::iequals(TAGNAME(childs.item(i)), _xmlNSPrefix + "else")) break; executeContent(childs.item(i)); @@ -1137,6 +1214,10 @@ void Interpreter::executeContent(const Arabica::DOM::Node& content) if (ifElem.hasChildNodes()) { NodeList elseifElem = ifElem.getElementsByTagNameNS(_nsURL, "elseif"); for (unsigned int i = 0; i < elseifElem.getLength(); i++) { +#if 0 + if (HAS_ATTR(elseifElem.item(i), "cond")) + std::cout << ATTR(elseifElem.item(i), "cond") << std::endl; +#endif if (hasConditionMatch(elseifElem.item(i))) { executeContent(elseifElem.item(i).getChildNodes()); goto ELSIF_ELEM_MATCH; @@ -1282,6 +1363,14 @@ void Interpreter::exitStates(const Arabica::XPath::NodeSet& enabled NodeSet statesToExit; std::set::iterator monIter; +#if 1 + std::cout << "Enabled exit transitions: " << std::endl; + for (int i = 0; i < enabledTransitions.size(); i++) { + std::cout << enabledTransitions[i] << std::endl; + } + std::cout << std::endl; +#endif + for (int i = 0; i < enabledTransitions.size(); i++) { Arabica::DOM::Element transition = ((Arabica::DOM::Element)enabledTransitions[i]); if (!isTargetless(transition)) { @@ -1306,15 +1395,36 @@ void Interpreter::exitStates(const Arabica::XPath::NodeSet& enabled tmpStates.push_back(source); tmpStates.insert(tmpStates.end(), tStates.begin(), tStates.end()); +#if 1 + std::cout << "tmpStates: "; + for (int i = 0; i < tmpStates.size(); i++) { + std::cout << ATTR(tmpStates[i], "id") << ", "; + } + std::cout << std::endl; +#endif ancestor = findLCCA(tmpStates); } +#if 1 + std::cout << "Ancestor: " << ATTR(ancestor, "id") << std::endl;; +#endif + for (int j = 0; j < _configuration.size(); j++) { if (isDescendant(_configuration[j], ancestor)) statesToExit.push_back(_configuration[j]); } } } + +#if 1 + std::cout << "States to exit: "; + for (int i = 0; i < statesToExit.size(); i++) { + std::cout << ATTR(statesToExit[i], "id") << ", "; + } + std::cout << std::endl; + +#endif + // remove statesToExit from _statesToInvoke std::list > tmp; for (int i = 0; i < _statesToInvoke.size(); i++) { @@ -1340,7 +1450,7 @@ void Interpreter::exitStates(const Arabica::XPath::NodeSet& enabled Arabica::DOM::Element historyElem = (Arabica::DOM::Element)histories[j]; std::string historyType = (historyElem.hasAttribute("type") ? historyElem.getAttribute("type") : "shallow"); NodeSet historyNodes; - for (int k = 0; k < _configuration.size(); k++) { + for (int k = 0; k < _configuration.size(); k++) { if (boost::iequals(historyType, "deep")) { if (isAtomic(_configuration[k]) && isDescendant(_configuration[k], statesToExit[i])) historyNodes.push_back(_configuration[k]); @@ -1350,6 +1460,15 @@ void Interpreter::exitStates(const Arabica::XPath::NodeSet& enabled } } _historyValue[historyElem.getAttribute("id")] = historyNodes; +#if 0 + std::cout << "History node " << ATTR(historyElem, "id") << " contains: "; + for (int i = 0; i < historyNodes.size(); i++) { + std::cout << ATTR(historyNodes[i], "id") << ", "; + } + std::cout << std::endl; + +#endif + } } @@ -1389,13 +1508,21 @@ void Interpreter::enterStates(const Arabica::XPath::NodeSet& enable NodeSet statesForDefaultEntry; std::set::iterator monIter; +#if 1 + std::cout << "Enabled enter transitions: " << std::endl; + for (int i = 0; i < enabledTransitions.size(); i++) { + std::cout << enabledTransitions[i] << std::endl; + } + std::cout << std::endl; +#endif + for (int i = 0; i < enabledTransitions.size(); i++) { Arabica::DOM::Element transition = ((Arabica::DOM::Element)enabledTransitions[i]); if (!isTargetless(transition)) { std::string transitionType = (boost::iequals(transition.getAttribute("type"), "internal") ? "internal" : "external"); NodeSet tStates = getTargetStates(transition); -#if 0 +#if 1 std::cout << "Target States: "; for (int i = 0; i < tStates.size(); i++) { std::cout << ATTR(tStates[i], "id") << ", "; @@ -1405,7 +1532,7 @@ void Interpreter::enterStates(const Arabica::XPath::NodeSet& enable Arabica::DOM::Node ancestor; Arabica::DOM::Node source = getSourceState(transition); -#if 0 +#if 1 std::cout << "Source States: " << ATTR(source, "id") << std::endl; #endif assert(source); @@ -1429,7 +1556,7 @@ void Interpreter::enterStates(const Arabica::XPath::NodeSet& enable ancestor = findLCCA(tmpStates); } -#if 0 +#if 1 std::cout << "Ancestor: " << ATTR(ancestor, "id") << std::endl; #endif @@ -1437,10 +1564,18 @@ void Interpreter::enterStates(const Arabica::XPath::NodeSet& enable addStatesToEnter(tStates[j], statesToEnter, statesForDefaultEntry); } +#if 1 + std::cout << "States to enter: "; + for (int i = 0; i < statesToEnter.size(); i++) { + std::cout << ATTR(statesToEnter[i], "id") << ", "; + } + std::cout << std::endl; +#endif + for (int j = 0; j < tStates.size(); j++) { NodeSet ancestors = getProperAncestors(tStates[j], ancestor); -#if 0 +#if 1 std::cout << "Proper Ancestors of " << ATTR(tStates[j], "id") << " and " << ATTR(ancestor, "id") << ": "; for (int i = 0; i < ancestors.size(); i++) { std::cout << ATTR(ancestors[i], "id") << ", "; @@ -1579,12 +1714,16 @@ void Interpreter::addStatesToEnter(const Arabica::DOM::Node& state, Arabica::XPath::NodeSet& statesToEnter, Arabica::XPath::NodeSet& statesForDefaultEntry) { std::string stateId = ((Arabica::DOM::Element)state).getAttribute("id"); - if (isHistory(state)) { + +#if 1 + std::cout << "Adding state to enter: " << stateId << std::endl; +#endif + if (isHistory(state)) { if (_historyValue.find(stateId) != _historyValue.end()) { Arabica::XPath::NodeSet historyValue = _historyValue[stateId]; -#if 0 - std::cout << "History States: "; +#if 1 + std::cout << "History State " << ATTR(state, "id") << ": "; for (int i = 0; i < historyValue.size(); i++) { std::cout << ATTR(historyValue[i], "id") << ", "; } @@ -1595,7 +1734,7 @@ void Interpreter::addStatesToEnter(const Arabica::DOM::Node& state, addStatesToEnter(historyValue[i], statesToEnter, statesForDefaultEntry); NodeSet ancestors = getProperAncestors(historyValue[i], state); -#if 0 +#if 1 std::cout << "Proper Ancestors: "; for (int i = 0; i < ancestors.size(); i++) { std::cout << ATTR(ancestors[i], "id") << ", "; @@ -1604,8 +1743,6 @@ void Interpreter::addStatesToEnter(const Arabica::DOM::Node& state, #endif for (int j = 0; j < ancestors.size(); j++) { - if (boost::iequals(TAGNAME(ancestors[j]), _xmlNSPrefix + "scxml")) // do not add the scxml element itself - continue; statesToEnter.push_back(ancestors[j]); } } @@ -1615,6 +1752,12 @@ void Interpreter::addStatesToEnter(const Arabica::DOM::Node& state, NodeSet targets = getTargetStates(transitions[i]); for (int j = 0; j < targets.size(); j++) { addStatesToEnter(targets[j], statesToEnter, statesForDefaultEntry); + + // Modifications from chris nuernberger + NodeSet ancestors = getProperAncestors(targets[j], state); + for (int k = 0; k < ancestors.size(); k++) { + statesToEnter.push_back(ancestors[k]); + } } } } @@ -1652,6 +1795,14 @@ Arabica::XPath::NodeSet Interpreter::getChildStates(const Arabica:: return childs; } +/** + See: http://www.w3.org/TR/scxml/#LCCA + The Least Common Compound Ancestor is the or element s such that s is a proper ancestor + of all states on stateList and no descendant of s has this property. Note that there is guaranteed to be + such an element since the wrapper element is a common ancestor of all states. Note also that since + we are speaking of proper ancestor (parent or parent of a parent, etc.) the LCCA is never a member of stateList. +*/ + Arabica::DOM::Node Interpreter::findLCCA(const Arabica::XPath::NodeSet& states) { #if 0 std::cout << "findLCCA: "; @@ -1662,9 +1813,11 @@ Arabica::DOM::Node Interpreter::findLCCA(const Arabica::XPath::Node #endif Arabica::XPath::NodeSet ancestors = getProperAncestors(states[0], Arabica::DOM::Node()); - ancestors.push_back(states[0]); // state[0] may already be the ancestor - bug in W3C spec? +// ancestors.push_back(states[0]); // state[0] may already be the ancestor - bug in W3C spec? Arabica::DOM::Node ancestor; for (int i = 0; i < ancestors.size(); i++) { + if (!isCompound(ancestors[i])) + continue; for (int j = 0; j < states.size(); j++) { #if 0 std::cout << "Checking " << TAGNAME(states[j]) << " and " << TAGNAME(ancestors[i]) << std::endl; @@ -1677,6 +1830,10 @@ Arabica::DOM::Node Interpreter::findLCCA(const Arabica::XPath::Node NEXT_ANCESTOR: ; } + + // take uppermost root as ancestor + if (!ancestor) + ancestor = _scxml; assert(ancestor); #if 0 std::cout << " -> " << ATTR(ancestor, "id") << " " << ancestor.getLocalName() << std::endl; @@ -1817,7 +1974,7 @@ NodeSet Interpreter::filterChildElements(const std::string& tagName NodeList childs = node.getChildNodes(); for (unsigned int i = 0; i < childs.getLength(); i++) { if (childs.item(i).getNodeType() != Node_base::ELEMENT_NODE || - !boost::iequals(LOCALNAME(childs.item(i)), tagName)) + !boost::iequals(TAGNAME(childs.item(i)), tagName)) continue; filteredChildElems.push_back(childs.item(i)); } @@ -1832,6 +1989,8 @@ NodeSet Interpreter::getProperAncestors(const Arabica::DOM::Node& state) { return true; if (boost::iequals("parallel", tagName)) return true; - if (boost::iequals("history", tagName)) - return true; +// if (boost::iequals("history", tagName)) // this is no state, see mail to W3C list +// return true; if (boost::iequals("final", tagName)) return true; return false; @@ -1963,7 +2122,7 @@ bool Interpreter::isCompound(const Arabica::DOM::Node& state) { if (!isState(state)) return false; - if (boost::iequals(LOCALNAME(state), "parallel")) + if (boost::iequals(LOCALNAME(state), "parallel")) // parallel is no compound state return false; Arabica::DOM::NodeList childs = state.getChildNodes(); @@ -2027,6 +2186,92 @@ void Interpreter::setCmdLineOptions(int argc, char** argv) { } } +/** + * See: http://www.w3.org/TR/scxml/#LegalStateConfigurations + */ +bool Interpreter::hasLegalConfiguration() { + +#if 0 + std::cout << "Checking whether {"; + std::string seperator; + for (int i = 0; i < _configuration.size(); i++) { + std::cout << seperator << ATTR(_configuration[i], "id"); + seperator = ", "; + } + std::cout << "} is legal" << std::endl; +#endif + + // The configuration contains exactly one child of the element. + NodeSet scxmlChilds = getChildStates(_scxml); + bool foundScxmlChild = false; + for (int i = 0; i < scxmlChilds.size(); i++) { + if (isMember(scxmlChilds[i], _configuration)) { + if (foundScxmlChild) + return false; + foundScxmlChild = true; + } + } + if (!foundScxmlChild) + return false; + + // The configuration contains one or more atomic states. + bool foundAtomicState = false; + for (int i = 0; i < _configuration.size(); i++) { + if (isAtomic(_configuration[i])) { + foundAtomicState = true; + break; + } + } + if (!foundAtomicState) + return false; + + // When the configuration contains an atomic state, it contains all of its and ancestors. + for (int i = 0; i < _configuration.size(); i++) { + if (isAtomic(_configuration[i])) { + Node parent = _configuration[i]; + while((parent = parent.getParentNode())) { + if (isState(parent) && + (boost::iequals(LOCALNAME(parent), "state") || + boost::iequals(LOCALNAME(parent), "parallel"))) { + if (!isMember(parent, _configuration)) + return false; + } + } + } + } + + // When the configuration contains a non-atomic , it contains one and only one of the state's children + for (int i = 0; i < _configuration.size(); i++) { + if (!isAtomic(_configuration[i]) && !isParallel(_configuration[i])) { + bool foundChildState = false; + NodeSet childs = getChildStates(_configuration[i]); + for (int j = 0; j < childs.size(); j++) { + if (isMember(childs[j], _configuration)) { + if (foundChildState) + return false; + foundChildState = true; + } + } + if (!foundChildState) + return false; + } + } + + // If the configuration contains a state, it contains all of its children + for (int i = 0; i < _configuration.size(); i++) { + if (isParallel(_configuration[i])) { + NodeSet childs = getChildStates(_configuration[i]); + for (int j = 0; j < childs.size(); j++) { + if (!isMember(childs[j], _configuration) && !isHistory(childs[j])) + return false; + } + } + } + + // everything worked out fine! + return true; +} + void Interpreter::dump() { if (!_document) return; diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h index ab58ec3..7b30fd9 100644 --- a/src/uscxml/Interpreter.h +++ b/src/uscxml/Interpreter.h @@ -151,7 +151,8 @@ public: static bool isMember(const Arabica::DOM::Node& node, const Arabica::XPath::NodeSet& set); void dump(); - + bool hasLegalConfiguration(); + static bool isState(const Arabica::DOM::Node& state); static bool isPseudoState(const Arabica::DOM::Node& state); static bool isTransitionTarget(const Arabica::DOM::Node& elem); @@ -247,6 +248,8 @@ protected: bool isWithinSameChild(const Arabica::DOM::Node& transition); bool parentIsScxmlState(Arabica::DOM::Node state); + Arabica::DOM::Node getTransitionSubgraph(const Arabica::DOM::Node& transition); + static std::vector tokenizeIdRefs(const std::string& idRefs); static boost::uuids::random_generator uuidGen; diff --git a/src/uscxml/concurrency/eventqueue/DelayedEventQueue.h b/src/uscxml/concurrency/eventqueue/DelayedEventQueue.h index 84ab16e..fc00ec0 100644 --- a/src/uscxml/concurrency/eventqueue/DelayedEventQueue.h +++ b/src/uscxml/concurrency/eventqueue/DelayedEventQueue.h @@ -37,6 +37,10 @@ public: void stop(); static void run(void*); + bool isEmpty() { + return _callbackData.empty(); + } + static void timerCallback(evutil_socket_t fd, short what, void *arg); static void dummyCallback(evutil_socket_t fd, short what, void *arg); diff --git a/test/run-scxml-test-framework.sh b/test/run-scxml-test-framework.sh index 2182e79..e20afe9 100755 --- a/test/run-scxml-test-framework.sh +++ b/test/run-scxml-test-framework.sh @@ -27,13 +27,13 @@ TESTS="" # TESTS="${TESTS} scxml-test-framework/test/actionSend/send4.scxml" # won't support # TESTS="${TESTS} scxml-test-framework/test/actionSend/send5.scxml" # won't support # TESTS="${TESTS} scxml-test-framework/test/actionSend/send6.scxml" # won't support -# TESTS="${TESTS} scxml-test-framework/test/actionSend/send7.scxml" # won't support +# TESTS="${TESTS} scxml-test-framework/test/actionSend/send7.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/actionSend/send8.scxml" # won't support # TESTS="${TESTS} scxml-test-framework/test/assign-current-small-step/test0.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/assign-current-small-step/test1.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/assign-current-small-step/test2.scxml" # passed -# TESTS="${TESTS} scxml-test-framework/test/assign-current-small-step/test3.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/assign-current-small-step/test3.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/assign-current-small-step/test4.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/assign-next-small-step/test0.scxml" # failed @@ -43,8 +43,8 @@ TESTS="" # TESTS="${TESTS} scxml-test-framework/test/atom3-basic-tests/m0.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/atom3-basic-tests/m1.scxml" # passed -# TESTS="${TESTS} scxml-test-framework/test/atom3-basic-tests/m2.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/atom3-basic-tests/m3.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/atom3-basic-tests/m2.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/atom3-basic-tests/m3.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/basic/basic0.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/basic/basic1.scxml" # passed @@ -53,80 +53,80 @@ TESTS="" # TESTS="${TESTS} scxml-test-framework/test/cond-js/test0.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/cond-js/test1.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/cond-js/test2.scxml" # passed -# TESTS="${TESTS} scxml-test-framework/test/cond-js/TestConditionalTransition.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/cond-js/TestConditionalTransition.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/default-initial-state/initial1.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/default-initial-state/initial2.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/default-initial-state/initial3.scxml" # passed -# TESTS="${TESTS} scxml-test-framework/test/delayedSend/send1.scxml" # segfault -# TESTS="${TESTS} scxml-test-framework/test/delayedSend/send2.scxml" # segfault -# TESTS="${TESTS} scxml-test-framework/test/delayedSend/send3.scxml" # segfault +# TESTS="${TESTS} scxml-test-framework/test/delayedSend/send1.scxml" # won't support: stable config is c not b +# TESTS="${TESTS} scxml-test-framework/test/delayedSend/send2.scxml" # won't support: stable config is c not b +# TESTS="${TESTS} scxml-test-framework/test/delayedSend/send3.scxml" # won't support: stable config is c not b # TESTS="${TESTS} scxml-test-framework/test/documentOrder/documentOrder0.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/foreach/test1.scxml" # passed -# TESTS="${TESTS} scxml-test-framework/test/hierarchy/hier0.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/hierarchy/hier1.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/hierarchy/hier2.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/hierarchy/hier0.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/hierarchy/hier1.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/hierarchy/hier2.scxml" # passed -# TESTS="${TESTS} scxml-test-framework/test/hierarchy+documentOrder/test0.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/hierarchy+documentOrder/test1.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/hierarchy+documentOrder/test0.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/hierarchy+documentOrder/test1.scxml" # passed -TESTS="${TESTS} scxml-test-framework/test/history/history0.scxml" # segfault -# TESTS="${TESTS} scxml-test-framework/test/history/history1.scxml" # segfault -# TESTS="${TESTS} scxml-test-framework/test/history/history2.scxml" # segfault -# TESTS="${TESTS} scxml-test-framework/test/history/history3.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/history/history4.scxml" # segfault -# TESTS="${TESTS} scxml-test-framework/test/history/history5.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/history/history6.scxml" # segfault +# TESTS="${TESTS} scxml-test-framework/test/history/history0.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/history/history1.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/history/history2.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/history/history3.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/history/history4.scxml" # passed: removed history from "getChildStates" - see mail to w3c list +# TESTS="${TESTS} scxml-test-framework/test/history/history5.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/history/history6.scxml" # passed -# TESTS="${TESTS} scxml-test-framework/test/if-else/test0.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/if-else/test0.scxml" # failed: we enter state b with a === 11 -# TESTS="${TESTS} scxml-test-framework/test/in/TestInPredicate.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/in/TestInPredicate.scxml" # passed -# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test0.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test1.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test2.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test3.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test4.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test5.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test6.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test7.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test8.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test9.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test0.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test1.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test2.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test3.scxml" # failed: entered a1, b2 instead of a2, b2 +# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test4.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test5.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test6.scxml" # failed: entered a11, b12 instead of a22, b12 +# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test7.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test8.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/more-parallel/test9.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/multiple-events-per-transition/test1.scxml" # passed -# TESTS="${TESTS} scxml-test-framework/test/parallel/test0.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/parallel/test1.scxml" # exception -# TESTS="${TESTS} scxml-test-framework/test/parallel/test2.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/parallel/test3.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/parallel/test0.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/parallel/test1.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/parallel/test2.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/parallel/test3.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test0.scxml" # failed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test1.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test10.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test10.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test11.scxml" # failed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test12.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test13.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test13.scxml" # failed: transitioning to d not {c1, c2} on t # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test14.scxml" # failed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test15.scxml" # failed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test16.scxml" # failed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test17.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test18.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test18.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test19.scxml" # failed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test2.scxml" # failed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test20.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test21.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test21.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test22.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test23.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test23.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test24.scxml" # failed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test25.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test26.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test26.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test27.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test28.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test29.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test28.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test29.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test3.scxml" # failed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test30.scxml" # failed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test31.scxml" # failed @@ -134,8 +134,8 @@ TESTS="${TESTS} scxml-test-framework/test/history/history0.scxml" # segfault # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test5.scxml" # failed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test6.scxml" # failed # TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test7.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test8.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test9.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test8.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/parallel+interrupt/test9.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/script/test0.scxml" # getData not defined # TESTS="${TESTS} scxml-test-framework/test/script/test1.scxml" # getData not defined @@ -149,13 +149,13 @@ TESTS="${TESTS} scxml-test-framework/test/history/history0.scxml" # segfault # TESTS="${TESTS} scxml-test-framework/test/scxml-prefix-event-name-matching/test0.scxml" # passed # TESTS="${TESTS} scxml-test-framework/test/scxml-prefix-event-name-matching/test1.scxml" # passed -# TESTS="${TESTS} scxml-test-framework/test/send-data/send1.scxml" # segfault -# TESTS="${TESTS} scxml-test-framework/test/send-internal/test0.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/send-data/send1.scxml" # failed: typing issue with === +# TESTS="${TESTS} scxml-test-framework/test/send-internal/test0.scxml" # failed: typing issue with === # TESTS="${TESTS} scxml-test-framework/test/targetless-transition/test0.scxml" # passed -# TESTS="${TESTS} scxml-test-framework/test/targetless-transition/test1.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/targetless-transition/test2.scxml" # failed -# TESTS="${TESTS} scxml-test-framework/test/targetless-transition/test3.scxml" # failed +# TESTS="${TESTS} scxml-test-framework/test/targetless-transition/test1.scxml" # passed +# TESTS="${TESTS} scxml-test-framework/test/targetless-transition/test2.scxml" # passed +TESTS="${TESTS} scxml-test-framework/test/targetless-transition/test3.scxml" # failed #trap 'killall ${SCXML_TEST_FRAMEWORK_NAME}' 0 diff --git a/test/scxml-test-framework/test/history/history0.json b/test/scxml-test-framework/test/history/history0.json index c6afbd6..b614a61 100644 --- a/test/scxml-test-framework/test/history/history0.json +++ b/test/scxml-test-framework/test/history/history0.json @@ -3,11 +3,11 @@ "events" : [ { "event" : { "name" : "t1" }, - "nextConfiguration" : ["b", "b2"] + "nextConfiguration" : ["b2"] }, { "event" : { "name" : "t2" }, - "nextConfiguration" : ["b", "b3"] + "nextConfiguration" : ["b3"] }, { "event" : { "name" : "t3" }, @@ -15,7 +15,7 @@ }, { "event" : { "name" : "t1" }, - "nextConfiguration" : ["b", "b3"] + "nextConfiguration" : ["b3"] } ] } diff --git a/test/scxml-test-framework/test/send-data/send1.scxml b/test/scxml-test-framework/test/send-data/send1.scxml index 92c9c03..d150ad5 100644 --- a/test/scxml-test-framework/test/send-data/send1.scxml +++ b/test/scxml-test-framework/test/send-data/send1.scxml @@ -27,7 +27,7 @@ - + @@ -41,7 +41,7 @@ _event.data.bif === 3 && _event.data.belt === 4"> - + More content. diff --git a/test/src/scxml-test-framework-client.cpp b/test/src/scxml-test-framework-client.cpp index 1505988..841df0f 100644 --- a/test/src/scxml-test-framework-client.cpp +++ b/test/src/scxml-test-framework-client.cpp @@ -36,11 +36,12 @@ public: reply.compound["sessionToken"] = uscxml::Data(interpreter->getName()); std::string seperator; for (size_t i = 0; i < configuration.size(); i++) { - reply.compound["nextConfiguration"].array.push_back(uscxml::Data(ATTR(configuration[i], "id"), uscxml::Data::VERBATIM)); + if (uscxml::Interpreter::isAtomic(configuration[i])) + reply.compound["nextConfiguration"].array.push_back(uscxml::Data(ATTR(configuration[i], "id"), uscxml::Data::VERBATIM)); } -// std::cout << "---- reply:" << std::endl; -// std::cout << reply << std::endl; + std::cout << "---- reply:" << std::endl; + std::cout << reply << std::endl; std::stringstream replyString; replyString << reply; @@ -72,6 +73,11 @@ public: std::cout << std::endl; } virtual void beforeExitingStates(uscxml::Interpreter* interpreter, const Arabica::XPath::NodeSet& statesToExit) { + std::cout << "Configuration: "; + for (int i = 0; i < interpreter->getConfiguration().size(); i++) { + std::cout << ATTR(interpreter->getConfiguration()[i], "id") << ", "; + } + std::cout << std::endl; std::cout << "Exiting states: "; for (int i = 0; i < statesToExit.size(); i++) { std::cout << ATTR(statesToExit[i], "id") << ", "; @@ -88,7 +94,7 @@ public: virtual void httpRecvReq(struct evhttp_request *req) { -// std::cout << "---- received:" << std::endl; + std::cout << "---- received:" << std::endl; if (evhttp_request_get_command(req) != EVHTTP_REQ_POST) return; @@ -117,7 +123,7 @@ public: } uscxml::Data jsonReq = uscxml::Data::fromJSON(content); -// std::cout << jsonReq << std::endl; + std::cout << jsonReq << std::endl; // is this a load request? -- cgit v0.12