- }
- }
- Transition tr3: cp cp0 -> idle
- Transition tr4: cp cp0 -> terminate {
- cond {
- "tcCurrentIdx >= self->constData->fct.size"
- }
- }
- ChoicePoint cp0
- State idle {
- entry {
- "if(sequentialExecution)"
- "\tfct[tcCurrentIdx].startTestCase();"
- }
- }
- State terminate {
- entry {
- "etUnit_testFinished(-1);"
- }
- }
- }
- }
- }
-
- ProtocolClass PTestLifecycle {
+ ProtocolClass PTestControl {
incoming {
- Message finishedTestCase()
+ /**
+ * Start test execution.
+ */
+ Message start()
+
+ /**
+ * Abort test execution.
+ */
+ Message abort()
}
outgoing {
- Message startTestCase()
+ /**
+ * Test execution finished or aborted.
+ */
+ Message done(success : boolean)
}
+// semantics {
+// in:start -> out:done
+// in:abort -> out:done
+// }
}
}
\ No newline at end of file
diff --git a/runtime/org.eclipse.etrice.modellib.cpp/model/Tests.room b/runtime/org.eclipse.etrice.modellib.cpp/model/Tests.room
index 48e49e03d..097b72e5e 100644
--- a/runtime/org.eclipse.etrice.modellib.cpp/model/Tests.room
+++ b/runtime/org.eclipse.etrice.modellib.cpp/model/Tests.room
@@ -1,10 +1,11 @@
-RoomModel room.basic.etunit {
-
- import room.basic.types.* from "Types.room"
+RoomModel room.basic.test {
+
+ import room.basic.service.timing.* from "TimingService.room"
+ import room.basic.types.* from "Types.room"
/**
* A SubSystemClass or ActorClass having this annotation is construed as an instance.
- * During generation the necessary instantiation (LogicalSystem, SubSystemRef etc.) and mapping will be created.
+ * During generation the necessary instantiation (LogicalSystem, SubSystemRef etc.) and mapping will be created.
*
* Must not have LogicalThreads. Globally only once allowed. Runtime execution on DefaultThread of given PhysicalSystem.
*
diff --git a/runtime/org.eclipse.etrice.modellib.java/model/Tests.room b/runtime/org.eclipse.etrice.modellib.java/model/Tests.room
index cb2097af7..097b72e5e 100644
--- a/runtime/org.eclipse.etrice.modellib.java/model/Tests.room
+++ b/runtime/org.eclipse.etrice.modellib.java/model/Tests.room
@@ -1,4 +1,4 @@
-RoomModel room.basic.etunit {
+RoomModel room.basic.test {
import room.basic.service.timing.* from "TimingService.room"
import room.basic.types.* from "Types.room"
@@ -14,169 +14,4 @@ RoomModel room.basic.etunit {
target = { SubSystemClass, ActorClass }
}
- /**
- * Creates an etUnit test suite. Test cases can be added by creating instances of ActorClass TestSuiteActor.
- */
- abstract ActorClass TestSuiteActor {
- Interface {
- SPP timer : PTimer
- SPP tcLifecycle : PTestLifecycle
- }
- Structure {
- LayerConnection relay_sap timer satisfied_by timingService.timer
- LayerConnection relay_sap tcLifecycle satisfied_by lifecycleActor.fct
- ActorRef timingService: ATimingService
- ActorRef lifecycleActor : TestLifecycleActor
- }
- Behavior {
- Operation getTestSuiteName() : string {
- "return getName();"
- }
- ctor {
- "etUnit_open(\"log/testlog\", getTestSuiteName());"
- "etUnit_openTestSuite(getTestSuiteName());"
- }
- dtor {
- "etUnit_closeTestSuite();"
- "etUnit_close();"
- }
- }
- }
-
- abstract async ActorClass TestCaseActor {
- Structure {
- Attribute tcTimeoutIgnore : boolean
- Attribute tcCaseId : int32
- SAP tcLifecycle : PTestLifecycle
- SAP tcTimer : PTimer
- }
- Behavior {
- Operation getTestCaseName() : string {
- "return getName();"
- }
- Operation startTimeout(timeMs: int32){
- "tcTimeoutIgnore = false;"
- "tcTimer.startTimeout(timeMs);"
- }
- Operation invalidateTimeout(){
- "tcTimeoutIgnore = true;"
- }
- StateMachine {
- Transition init: initial -> wait4Start {
- action {
- "invalidateTimeout();"
- }
- }
- Transition trFinish: tpFinish of testing -> finish
- Transition trTimeout: testing -> timeout {
- triggers {
-
- }
- action {
- "invalidateTimeout();"
- }
- }
- Transition tr0: wait4Start -> testing {
- triggers {
-
- }
- }
- State testing {
- subgraph {
- ExitPoint tpFinish
- }
- }
- State timeout {
- entry {
- "EXPECT_FALSE(tcCaseId, \"timeout\", true);"
- "etUnit_closeTestCase(tcCaseId);"
- "tcLifecycle.finishedTestCase();"
- }
- }
- State finish {
- entry {
- "etUnit_closeTestCase(tcCaseId);"
- "tcLifecycle.finishedTestCase();"
- }
- }
- State wait4Start {
- exit {
- "tcCaseId = etUnit_openTestCase(getTestCaseName());"
- }
- }
- }
- }
- }
-
- ActorClass TestLifecycleActor {
- Interface {
- SPP fct: PTestLifecycle
- }
- Structure {
- ServiceImplementation of fct
- Attribute entireTestTimeout : int32 = "5000"
- Attribute sequentialExecution : boolean = "true"
- Attribute tcCurrentIdx : int32 = "0"
- SAP timer : PTimer
- }
- Behavior {
- StateMachine {
- Transition init: initial -> idle {
- action {
- "//printf(\"TestLifecycleActor (%s) starting with %d test cases\\n\", getName(), fct.getReplication());"
- "if(fct.getReplication() == 0)"
- "\tetUnit_testFinished(-1);"
- "else"
- "\ttimer.startTimeout(entireTestTimeout);"
- ""
- "if(!sequentialExecution)"
- "\tfct.startTestCase();"
- }
- }
- Transition tr1: idle -> cp cp0 {
- triggers {
-
- }
- action {
- "tcCurrentIdx++;"
- }
- }
- Transition tr2: idle -> terminate {
- triggers {
-
- }
- }
- Transition tr3: cp cp0 -> idle
- Transition tr4: cp cp0 -> terminate {
- cond {
- "tcCurrentIdx >= fct.getReplication()"
- }
- }
- ChoicePoint cp0
- State idle {
- entry {
- "if(sequentialExecution)"
- "\tfct[tcCurrentIdx].startTestCase();"
- }
- }
- State terminate {
- entry {
- "etUnit_testFinished(-1);"
- }
- }
- }
- }
- }
-
- ProtocolClass PTestLifecycle {
- incoming {
- Message finishedTestCase()
- }
- outgoing {
- Message startTestCase()
- }
- }
-
}
\ No newline at end of file
diff --git a/runtime/org.eclipse.etrice.runtime.c/src/common/etUnit/etUnit.c b/runtime/org.eclipse.etrice.runtime.c/src/common/etUnit/etUnit.c
index b90ac2af4..2dd752a55 100644
--- a/runtime/org.eclipse.etrice.runtime.c/src/common/etUnit/etUnit.c
+++ b/runtime/org.eclipse.etrice.runtime.c/src/common/etUnit/etUnit.c
@@ -21,6 +21,8 @@
/*** member variables */
+static etInt16 etUnit_failedSuites = 0;
+
/* file handling */
static FILE* etUnit_reportfile = NULL;
@@ -131,6 +133,8 @@ void etUnit_close(void) {
else
etLogger_logErrorF("Error Counter: %ld", etUnit_errorCounter);
etLogger_logInfoF("************* TEST END **************");
+
+ etUnit_errorCounter = 0;
}
void etUnit_openTestSuite(const char* testSuiteName) {
@@ -140,6 +144,7 @@ void etUnit_openTestSuite(const char* testSuiteName) {
}
void etUnit_closeTestSuite(void) {
+ etUnit_failedSuites += (etUnit_isSuccessSuite()) ? 0 : 1;
}
etInt16 etUnit_openTestCase(const char* testCaseName) {
@@ -250,6 +255,16 @@ void expect_equal_void_ptr(etInt16 id, const char* message, const void* expected
}
}
+void expectEqualStr(etInt16 id, const char* message, const char* expected, const char* actual, const char* file, int line) {
+ if (!(expected || actual || strcmp(expected, actual) == 0)) {
+ char testresult[ETUNIT_FAILURE_TEXT_LEN];
+ sprintf(testresult, "%s: expected=%s, actual=%s", message, expected, actual);
+ etUnit_handleExpect(id, ET_FALSE, testresult, expected, actual, file, line);
+ } else {
+ etUnit_handleExpect(id, ET_TRUE, "", NULL, NULL, file, line);
+ }
+}
+
#ifdef ET_FLOAT32
void expectEqualFloat32(etInt16 id, const char* message, etFloat32 expected, etFloat32 actual, etFloat32 precision, const char* file, int line) {
expect_equal_float(id, message, expected, actual, precision, file, line);
@@ -321,6 +336,14 @@ etBool etUnit_isSuccess(etInt16 id) {
return etUnit_testcaseSuccess[id];
}
+etBool etUnit_isSuccessSuite() {
+ return etUnit_errorCounter == 0;
+}
+
+etBool etUnit_isSuccessAll() {
+ return etUnit_failedSuites == 0;
+}
+
/* private functions */
static void expect_equal_int(etInt16 id, const char* message, etInt32 expected, etInt32 actual, const char* file, int line) {
diff --git a/runtime/org.eclipse.etrice.runtime.c/src/common/etUnit/etUnit.h b/runtime/org.eclipse.etrice.runtime.c/src/common/etUnit/etUnit.h
index f891c37a5..b29080445 100644
--- a/runtime/org.eclipse.etrice.runtime.c/src/common/etUnit/etUnit.h
+++ b/runtime/org.eclipse.etrice.runtime.c/src/common/etUnit/etUnit.h
@@ -71,6 +71,14 @@ void etUnit_closeTestCase(etInt16 id);
* \param id the test case id
*/
etBool etUnit_isSuccess(etInt16 id);
+/**
+ * indicate success of current test suite
+ */
+etBool etUnit_isSuccessSuite();
+/**
+ * indicate success of all test suites
+ */
+etBool etUnit_isSuccessAll();
/**
* releases the \ref etRuntime_getTerminateSemaphore() and thus makes the program terminate
*
@@ -153,6 +161,10 @@ void etUnit_closeAll(etInt16 id);
#define EXPECT_EQUAL_PTR(id, msg, expected, actual) \
expect_equal_void_ptr(id, msg, (const void*) expected, (const void*) actual, __FILE__, __LINE__)
+/*
+ * Strings
+ */
+#define EXPECT_EQUAL_STR(id, msg, expected, actual) expectEqualStr(id, msg, expected, actual, __FILE__, __LINE__)
/*
* more specialized functions
@@ -358,6 +370,19 @@ void expectRangeFloat64(etInt16 id, const char* message, etFloat64 min, etFloat6
* \param line the line
*/
void expect_equal_void_ptr(etInt16 id, const char* msg, const void* expected, const void* actual, const char* file, int line);
+
+/**
+ * reports an error if two strings aren't equal
+ *
+ * \param id the test case id
+ * \param msg the result message
+ * \param expected the expected value
+ * \param actual the actual value
+ * \param file the file name with the test case
+ * \param line the line
+ */
+void expectEqualStr(etInt16 id, const char* msg, const char* expected, const char* actual, const char* file, int line);
+
/**
* start of a comparison of an expected order. Initially with this method
* a list of integers is passed. Later calls of \ref expectOrder(etInt16, const char* msg, etInt16, const char* int)
--
cgit v1.2.3