summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Radomski <sradomski@mintwerk.de>2016-01-18 14:07:16 (GMT)
committerStefan Radomski <sradomski@mintwerk.de>2016-01-18 14:07:16 (GMT)
commit6e96eafb9bf087c35cfe8e60196d0a2a1698d22b (patch)
tree9b1fe7e7abcae365d11d24d7494d1a00f40b9eaa
parent575c2711df910f0b8ecce277bf7333077e235855 (diff)
downloaduscxml-6e96eafb9bf087c35cfe8e60196d0a2a1698d22b.zip
uscxml-6e96eafb9bf087c35cfe8e60196d0a2a1698d22b.tar.gz
uscxml-6e96eafb9bf087c35cfe8e60196d0a2a1698d22b.tar.bz2
Fixed a memory leak in transformed C scaffolding
-rw-r--r--src/uscxml/transform/ChartToC.cpp62
-rw-r--r--test/src/test-c-machine.cpp20
-rwxr-xr-xtest/w3c/check-tests.pl23
3 files changed, 67 insertions, 38 deletions
diff --git a/src/uscxml/transform/ChartToC.cpp b/src/uscxml/transform/ChartToC.cpp
index aac1acf..f261ffd 100644
--- a/src/uscxml/transform/ChartToC.cpp
+++ b/src/uscxml/transform/ChartToC.cpp
@@ -216,10 +216,10 @@ void ChartToC::writeTypes(std::ostream& stream) {
stream << "typedef struct scxml_elem_foreach scxml_elem_foreach;" << std::endl;
stream << std::endl;
- stream << "typedef void* (*dequeue_internal_cb_t)(const scxml_ctx* ctx);" << std::endl;
- stream << "typedef void* (*dequeue_external_cb_t)(const scxml_ctx* ctx);" << std::endl;
- stream << "typedef int (*is_enabled_cb_t)(const scxml_ctx* ctx, const scxml_transition* transition, const void* event);" << std::endl;
- stream << "typedef int (*is_true_cb_t)(const scxml_ctx* ctx, const char* expr);" << std::endl;
+ stream << "typedef void* (*dequeue_internal_t)(const scxml_ctx* ctx);" << std::endl;
+ stream << "typedef void* (*dequeue_external_t)(const scxml_ctx* ctx);" << std::endl;
+ stream << "typedef int (*is_enabled_t)(const scxml_ctx* ctx, const scxml_transition* transition, const void* event);" << std::endl;
+ stream << "typedef int (*is_true_t)(const scxml_ctx* ctx, const char* expr);" << std::endl;
stream << "typedef int (*exec_content_t)(const scxml_ctx* ctx, const scxml_state* state, const void* event);" << std::endl;
stream << "typedef int (*raise_done_event_t)(const scxml_ctx* ctx, const scxml_state* state, const scxml_elem_donedata* donedata);" << std::endl;
stream << "typedef int (*invoke_t)(const scxml_ctx* ctx, const scxml_state* s, const scxml_invoke* x);" << std::endl;
@@ -339,10 +339,10 @@ void ChartToC::writeTypes(std::ostream& stream) {
stream << " void* user_data;" << std::endl;
stream << " void* event;" << std::endl;
stream << std::endl;
- stream << " dequeue_internal_cb_t dequeue_internal;" << std::endl;
- stream << " dequeue_external_cb_t dequeue_external;" << std::endl;
- stream << " is_enabled_cb_t is_enabled;" << std::endl;
- stream << " is_true_cb_t is_true;" << std::endl;
+ stream << " dequeue_internal_t dequeue_internal;" << std::endl;
+ stream << " dequeue_external_t dequeue_external;" << std::endl;
+ stream << " is_enabled_t is_enabled;" << std::endl;
+ stream << " is_true_t is_true;" << std::endl;
stream << " raise_done_event_t raise_done_event;" << std::endl;
stream << std::endl;
stream << " exec_content_log_t exec_content_log;" << std::endl;
@@ -491,7 +491,12 @@ void ChartToC::writeExecContent(std::ostream& stream) {
stream << std::endl;
}
- bool hasInitialState = false;
+ /*
+ gen/c/ecma/test412.scxml (Failed)
+ gen/c/ecma/test579.scxml (Failed)
+ */
+#if 0
+ bool hasInitialState = false;
NodeSet<std::string> initial = filterChildElements(_nsInfo.xmlNSPrefix + "initial", state);
if (initial.size() > 0) {
NodeSet<std::string> initialTransition = filterChildElements(_nsInfo.xmlNSPrefix + "transition", initial);
@@ -505,16 +510,16 @@ void ChartToC::writeExecContent(std::ostream& stream) {
stream << std::endl;
}
}
-
+#endif
if (onentry.size() > 0) {
stream << "static int " << DOMUtils::idForNode(state) << "_on_entry(const scxml_ctx* ctx, const scxml_state* state, const void* event) {" << std::endl;
for (size_t j = 0; j < onentry.size(); j++) {
stream << " " << DOMUtils::idForNode(state) << "_on_entry_" << toStr(j) << "(ctx, state, event);" << std::endl;
}
- if (hasInitialState) {
- stream << " " << DOMUtils::idForNode(state) << "_initial" << "(ctx, state, event);" << std::endl;
- }
+// if (hasInitialState) {
+// stream << " " << DOMUtils::idForNode(state) << "_initial" << "(ctx, state, event);" << std::endl;
+// }
stream << " return SCXML_ERR_OK;" << std::endl;
stream << "}" << std::endl;
@@ -536,8 +541,8 @@ void ChartToC::writeExecContent(std::ostream& stream) {
for (size_t i = 0; i < _transitions.size(); i++) {
Element<std::string> transition(_transitions[i]);
- if (iequals(TAGNAME_CAST(transition.getParentNode()), "initial"))
- continue;
+// if (iequals(TAGNAME_CAST(transition.getParentNode()), "initial"))
+// continue;
NodeSet<std::string> execContent = filterChildType(Node_base::ELEMENT_NODE, transition);
@@ -1087,30 +1092,33 @@ void ChartToC::writeStates(std::ostream& stream) {
void ChartToC::writeTransitions(std::ostream& stream) {
-#if 0
// cross reference transition by document order - is this really needed?!
std::set<std::string> elements;
elements.insert(_nsInfo.xmlNSPrefix + "transition");
NodeSet<std::string> transDocOrder = inDocumentOrder(elements, _scxml);
- stream << "static const " << _transDataType << " scxml_transitions_doc_order[" << toStr(_transitions.size()) << "] = {" << std::endl;
- stream << " ";
+ std::stringstream transDocOrderSS;
std::string seperator = "";
for (size_t i = 0; i < transDocOrder.size(); i++) {
Element<std::string> transition(_transitions[i]);
transition.setAttribute("documentOrder", toStr(i));
- stream << seperator << ATTR(transition, "postFixOrder");
+ transDocOrderSS << seperator << ATTR(transition, "postFixOrder");
seperator = ", ";
}
- stream << std::endl << "};" << std::endl;
- stream << std::endl;
+#if 0
+ stream << "static const " << _transDataType << " scxml_transitions_doc_order[" << toStr(_transitions.size()) << "] = {" << std::endl;
+ stream << " " << transDocOrderSS;
+ stream << std::endl << "};" << std::endl;
+ stream << std::endl;
#endif
stream << "static const scxml_transition scxml_transitions[" << toStr(_transitions.size()) << "] = {" << std::endl;
for (size_t i = 0; i < _transitions.size(); i++) {
Element<std::string> transition(_transitions[i]);
- stream << " { /* transition number " << ATTR(transition, "documentOrder") << " with priority " << toStr(i) << " */" << std::endl;
+ stream << " { /* transition number " << ATTR(transition, "documentOrder") << " with priority " << toStr(i) << std::endl;
+ stream << " target: " << ATTR(transition, "target") << std::endl;
+ stream << " */" << std::endl;
/**
uint16_t source;
@@ -1167,8 +1175,8 @@ void ChartToC::writeTransitions(std::ostream& stream) {
// on transition handlers
stream << " /* ontrans */ ";
- if (filterChildType(Arabica::DOM::Node_base::ELEMENT_NODE, transition).size() > 0 &&
- !iequals(TAGNAME_CAST(transition.getParentNode()), "initial")) {
+ if (filterChildType(Arabica::DOM::Node_base::ELEMENT_NODE, transition).size() > 0 /* &&
+ !iequals(TAGNAME_CAST(transition.getParentNode()), "initial") */) {
stream << DOMUtils::idForNode(transition) + "_on_trans";
} else {
stream << "NULL";
@@ -1525,7 +1533,7 @@ void ChartToC::writeFSM(std::ostream& stream) {
stream << "// TAKE_TRANSITIONS:" << std::endl;
stream << " for (size_t i = 0; i < SCXML_NUMBER_TRANSITIONS; i++) {" << std::endl;
- stream << " if (IS_SET(i, trans_set) && (scxml_transitions[i].type & SCXML_TRANS_HISTORY) == 0) {" << std::endl;
+ stream << " if (IS_SET(i, trans_set) && (scxml_transitions[i].type & (SCXML_TRANS_HISTORY | SCXML_TRANS_INITIAL)) == 0) {" << std::endl;
stream << " // call executable content in transition" << std::endl;
stream << " if (scxml_transitions[i].on_transition != NULL) {" << std::endl;
stream << " if unlikely((err = scxml_transitions[i].on_transition(ctx," << std::endl;
@@ -1571,10 +1579,10 @@ void ChartToC::writeFSM(std::ostream& stream) {
stream << " }" << std::endl;
stream << std::endl;
- stream << " // take history transitions" << std::endl;
+ stream << " // take history and initial transitions" << std::endl;
stream << " for (size_t j = 0; j < SCXML_NUMBER_TRANSITIONS; j++) {" << std::endl;
stream << " if unlikely(IS_SET(j, trans_set) &&" << std::endl;
- stream << " (scxml_transitions[j].type & SCXML_TRANS_HISTORY) &&" << std::endl;
+ stream << " (scxml_transitions[j].type & (SCXML_TRANS_HISTORY | SCXML_TRANS_INITIAL)) &&" << std::endl;
stream << " scxml_states[scxml_transitions[j].source].parent == i) {" << std::endl;
stream << " // call executable content in transition" << std::endl;
stream << " if (scxml_transitions[j].on_transition != NULL) {" << std::endl;
diff --git a/test/src/test-c-machine.cpp b/test/src/test-c-machine.cpp
index 35f06a4..33c149a 100644
--- a/test/src/test-c-machine.cpp
+++ b/test/src/test-c-machine.cpp
@@ -127,7 +127,7 @@ int matches(const char* desc, const char* event) {
int exec_content_raise(const scxml_ctx* ctx, const char* event) {
Event* e = new Event();
- e->name = strdup(event);
+ e->name = event;
if (boost::starts_with(e->name, "error.")) {
e->eventType = Event::PLATFORM;
@@ -216,8 +216,10 @@ int raise_done_event(const scxml_ctx* ctx, const scxml_state* state, const scxml
void delayedSend(void* ctx, std::string eventName) {
tthread::lock_guard<tthread::mutex> lock(USER_DATA(ctx)->mutex);
- SendRequest* e = USER_DATA(ctx)->sendIds[eventName];
- if (e->target == "#_internal") {
+ SendRequest* sr = USER_DATA(ctx)->sendIds[eventName];
+ Event* e = new Event(*sr);
+
+ if (sr->target == "#_internal") {
e->eventType = Event::INTERNAL;
#ifdef SCXML_VERBOSE
printf("Pushing Internal Event: %s\n", e->name.c_str());
@@ -231,6 +233,7 @@ void delayedSend(void* ctx, std::string eventName) {
USER_DATA(ctx)->eq.push_back(e);
}
USER_DATA(ctx)->monitor.notify_all();
+ delete sr;
}
int exec_content_cancel(const scxml_ctx* ctx, const char* sendid, const char* sendidexpr) {
@@ -300,8 +303,9 @@ int exec_content_send(const scxml_ctx* ctx, const scxml_elem_send* send) {
} else {
e->type = "http://www.w3.org/TR/scxml/#SCXMLEventProcessor";
}
- } catch (Event e) {
- exec_content_raise(ctx, e.name.c_str());
+ } catch (Event exc) {
+ exec_content_raise(ctx, exc.name.c_str());
+ delete e;
return SCXML_ERR_EXEC_CONTENT;
}
@@ -317,7 +321,7 @@ int exec_content_send(const scxml_ctx* ctx, const scxml_elem_send* send) {
if (send->eventexpr != NULL) {
e->name = USER_DATA(ctx)->datamodel.evalAsString(send->eventexpr);
} else {
- e->name = strdup(send->event);
+ e->name = send->event;
}
try {
@@ -367,12 +371,12 @@ int exec_content_send(const scxml_ctx* ctx, const scxml_elem_send* send) {
}
}
- const char* sendid = NULL;
+ std::string sendid;
if (send->id != NULL) {
sendid = send->id;
e->sendid = sendid;
} else {
- sendid = strdup(UUID::getUUID().c_str());
+ sendid = UUID::getUUID();
if (send->idlocation != NULL) {
USER_DATA(ctx)->datamodel.assign(send->idlocation, Data(sendid, Data::VERBATIM));
} else {
diff --git a/test/w3c/check-tests.pl b/test/w3c/check-tests.pl
index 7299947..71218f4 100755
--- a/test/w3c/check-tests.pl
+++ b/test/w3c/check-tests.pl
@@ -4,6 +4,13 @@ use strict;
use Data::Dumper;
use XML::Simple;
+my @failed;
+# failing for C transformation
+# @failed = qw/
+# 187 191 192 207 215 216 220 223 224 225 226 228 229 230 232 233 234 235
+# 236 237 239 240 241 242 243 244 245 247 250 252 253 276 338 347 422 530
+# 554 201 496 500 501 509 510 518 519 520 521 522 531 532 534 567 569 577
+# 301 307 446 552 557 558 561/;
my $manifest = XMLin("./manifest.xml");
# print Dumper($manifest->{'assert'});
@@ -17,7 +24,7 @@ my @agnosticTests;
my @nullTests;
my @manualTests;
-for my $testNr (keys $manifest->{'assert'}) {
+TESTS: for my $testNr (keys $manifest->{'assert'}) {
my @tests;
my $thisTest = $manifest->{'assert'}->{$testNr};
if (ref($thisTest->{'test'}->{'start'}) eq "ARRAY") {
@@ -25,7 +32,17 @@ for my $testNr (keys $manifest->{'assert'}) {
} else {
push (@tests, $thisTest->{'test'}->{'start'});
}
+ for my $t (@tests) {
+ if ($t->{'uri'} =~ /\/test(.*)\.[txml|txt]/) {
+ next TESTS if ( grep /^$1$/, @failed );
+ $perSpecId->{$thisTest->{'specnum'}.':'.$thisTest->{'specid'}}->{'tests'} .= $1." ";
+ } else {
+ die(Dumper($t));
+ }
+ }
+
$perSpecId->{$thisTest->{'specnum'}.':'.$thisTest->{'specid'}}->{'total'} += @tests;
+
if ($thisTest->{'test'}->{'manual'} eq "true") {
$perSpecId->{$thisTest->{'specnum'}.':'.$thisTest->{'specid'}}->{'manual'} += @tests;
push @manualTests, @tests;
@@ -43,7 +60,7 @@ for my $testNr (keys $manifest->{'assert'}) {
if ($thisTest->{'specid'} eq "#xpath-profile" || $thisTest->{'specid'} !~ /profile$/) {
push @xpathTests, @tests;
}
-
+
push (@allTests, @tests);
push @agnosticTests, @tests if ($thisTest->{'specid'} !~ /profile$/);
}
@@ -81,7 +98,7 @@ for my $datamodel (keys %datamodels) {
}
}
-# print Dumper(@manualTests);
+print Dumper($perSpecId);
print "NULL : ".@nullTests."\n";
print "ECMA : ".@ecmaTests."\n";