Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Eclipse Projects
Eclipse eTrice™
Eclipse eTrice
Commits
a01439a7
Commit
a01439a7
authored
Mar 03, 2022
by
Juergen Haug
Browse files
added etUnit2 API with "etunit" module prefix
parent
2a869e81
Changes
4
Expand all
Hide whitespace changes
Inline
Side-by-side
runtime/org.eclipse.etrice.runtime.c/src/common/etUnit/etUnit.c
View file @
a01439a7
This diff is collapsed.
Click to expand it.
runtime/org.eclipse.etrice.runtime.c/src/common/etUnit/etUnit.h
View file @
a01439a7
...
...
@@ -13,114 +13,16 @@
*******************************************************************************/
/**
* \file etUnit.h
*
* a collection of methods for unit testing. The component uses a very simple file output format
* which is translated into JUnit xml format by a separate tool written in Java and also part of the
* eTrice project
*
* \author Thomas Schuetz
* etUnit API without module prefix
*/
#ifndef _ETUNIT_H_
#define _ETUNIT_H_
#include "etDatatypes.h"
#include <string.h>
#include "etUnit2.h"
ET_EXTERN_C_BEGIN
// compile time evaluated
#define ETUNIT_FILENAME (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__))
typedef
void
(
*
etUnit_WriteFunction
)(
void
*
handle
,
const
char
*
format
,
...);
/**
* opens a file to protocol the test results
*
* \param testResultPath the file path
* \param testFileName the file name
*/
void
etUnit_open
(
const
char
*
testResultPath
,
const
char
*
testFileName
);
/**
* closes the protocol file
*/
void
etUnit_close
(
void
);
/**
* opens a test suite which is a collection of test cases
*
* \param testSuiteName the name of the suite
*/
void
etUnit_openTestSuite
(
const
char
*
testSuiteName
);
/**
* closes the currently open test suite
*/
void
etUnit_closeTestSuite
(
void
);
/**
* enable support for parallel test cases (default false)
*/
void
etUnit_setParallelTestCases
(
etBool
enabled
);
/**
* write etunit output to callback
*/
void
etUnit_setWriteFunction
(
etUnit_WriteFunction
fct
);
/**
* opens a test case. Multiple test cases can be open at a time
*
* \param testCaseName the name of the test case
*
* \return in case of parallel testing an id which has to be used as an identifier
* for the expects and other methods, otherwise zero
*/
etInt16
etUnit_openTestCase
(
const
char
*
testCaseName
);
/**
* closes a test case
*
* \param id the test case id
*/
void
etUnit_closeTestCase
(
etInt16
id
);
/**
* skips a test case
*
* \param id the test case id
* \param msg the message or reason
*/
void
etUnit_skipTestCase
(
etInt16
id
,
const
char
*
msg
);
/**
* indicate success of a test case
*
* \param id the test case id
*/
etBool
etUnit_isSuccess
(
etInt16
id
);
/**
* releases the \ref etRuntime_getTerminateSemaphore() and thus makes the program terminate
*
* \param id (unused)
*/
void
etUnit_testFinished
(
etInt16
id
);
/* functions for more convenience for model and generator tests */
/**
* opens a file, test suite and test case
*
* \param testResultPath the file path
* \param testFileName the file name
* \param testSuiteName the name of the suite
* \param testCaseName the name of the test case
*
* \return an id for the test case which has to be used as an identifier
* for the expect... and other methods
*/
etInt16
etUnit_openAll
(
const
char
*
testResultPath
,
const
char
*
testFileName
,
const
char
*
testSuiteName
,
const
char
*
testCaseName
);
/**
* closes test case, suite and file
*
* \param id the test case id
*/
void
etUnit_closeAll
(
etInt16
id
);
/*
* boolean values
*/
...
...
@@ -194,283 +96,6 @@ void etUnit_closeAll(etInt16 id);
/** calls \ref expectOrderEnd() */
#define EXPECT_ORDER_END(id, msg, val) expectOrderEnd(id, msg, val, ETUNIT_FILENAME, __LINE__)
/*
* Alternative expects omitting id argument (without parallel testing)
*/
#define ETUNIT_TRUE(msg, condition) expectTrue(0, msg, condition, ETUNIT_FILENAME, __LINE__)
#define ETUNIT_FALSE(msg, condition) expectFalse(0, msg, condition, ETUNIT_FILENAME, __LINE__)
#define ETUNIT_FAIL(msg) expectFail(0, msg, ETUNIT_FILENAME, __LINE__)
#define ETUNIT_EQUAL_INT(msg, expected, actual) expectEqualInt32(0, msg, expected, actual, ETUNIT_FILENAME, __LINE__)
#define ETUNIT_EQUAL_UINT(msg, expected, actual) expectEqualUInt32(0, msg, expected, actual, ETUNIT_FILENAME, __LINE__)
#ifdef ET_FLOAT32
#define ETUNIT_EQUAL_FLOAT32(msg, expected, actual, precision) expectEqualFloat32(0, msg, expected, actual, precision, ETUNIT_FILENAME, __LINE__)
#define ETUNIT_RANGE_FLOAT32(msg, min, max, actual) expectRangeFloat32(0, msg, min, max, actual, ETUNIT_FILENAME, __LINE__)
#endif
#ifdef ET_FLOAT64
#define ETUNIT_EQUAL_FLOAT64(msg, expected, actual, precision) expectEqualFloat64(0, msg, expected, actual, precision, ETUNIT_FILENAME, __LINE__)
#define ETUNIT_RANGE_FLOAT64(msg, min, max, actual) expectRangeFloat64(0, msg, min, max, actual, ETUNIT_FILENAME, __LINE__)
#endif
#define ETUNIT_EQUAL_PTR(msg, expected, actual) \
expect_equal_void_ptr(ETUNIT_SINGLETON_TEST_CASE_ID, msg, (const void*) expected, (const void*) actual, ETUNIT_FILENAME, __LINE__)
#define ETUNIT_EQUAL_STR(msg, expected, actual) expectEqualStr(0, msg, expected, actual, ETUNIT_FILENAME, __LINE__)
#define ETUNIT_ORDER_START(list, size) expectOrderStart(0, list, size, ETUNIT_FILENAME, __LINE__)
#define ETUNIT_ORDER(msg, val) expectOrder(0, msg, val, ETUNIT_FILENAME, __LINE__)
#define ETUNIT_ORDER_END(msg, val) expectOrderEnd(0, msg, val, ETUNIT_FILENAME, __LINE__)
/*
* Helpers for adding test cases
*/
/**
* code block with calls \ref etUnit_openTestCase() followed by a call to the passed
* test case followed by a call to \ref etUnit_closeTestCase
*
* \param testcase the name of a test case method
*/
#define ADD_TESTCASE(testcase) \
{ etInt16 id = etUnit_openTestCase(#testcase); \
testcase(id); \
etUnit_closeTestCase(id);}
/*
* function prototypes, use above macros to call them
*/
/**
* reports an error if the condition is <code>false</code>
*
* \param id the test case id
* \param msg the result message
* \param condition the condition that is expected to be <code>true</code>
* \param file the file name with the test case
* \param line the line
*/
void
expectTrue
(
etInt16
id
,
const
char
*
msg
,
etBool
condition
,
const
char
*
file
,
int
line
);
/**
* reports an error if the condition is <code>true</code>
*
* \param id the test case id
* \param msg the result message
* \param condition the condition that is expected to be <code>false</code>
* \param file the file name with the test case
* \param line the line
*/
void
expectFalse
(
etInt16
id
,
const
char
*
msg
,
etBool
condition
,
const
char
*
file
,
int
line
);
/**
* reports an fail
*
* \param id the test case id
* \param msg the result message
* \param file the file name with the test case
* \param line the line
*/
void
expectFail
(
etInt16
id
,
const
char
*
msg
,
const
char
*
file
,
int
line
);
/**
* reports an error if two integers 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
expectEqualInt8
(
etInt16
id
,
const
char
*
msg
,
etInt8
expected
,
etInt8
actual
,
const
char
*
file
,
int
line
);
/**
* reports an error if a value is not inside a range e.g. [2, 123]
*
* \param id the test case id
* \param msg the result message
* \param min the lower limit (inclusive)
* \param max the upper limit (inclusive)
* \param actual the actual value
* \param file the file name with the test case
* \param line the line
*/
void
expectRangeInt8
(
etInt16
id
,
const
char
*
msg
,
etInt8
min
,
etInt8
max
,
etInt8
actual
,
const
char
*
file
,
int
line
);
/**
* reports an error if two integers 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
expectEqualInt16
(
etInt16
id
,
const
char
*
msg
,
etInt16
expected
,
etInt16
actual
,
const
char
*
file
,
int
line
);
/**
* reports an error if two integers 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
expectEqualInt32
(
etInt16
id
,
const
char
*
msg
,
etInt32
expected
,
etInt32
actual
,
const
char
*
file
,
int
line
);
/**
* reports an error if two integers 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
expectEqualUInt8
(
etInt16
id
,
const
char
*
msg
,
etUInt8
expected
,
etUInt8
actual
,
const
char
*
file
,
int
line
);
/**
* reports an error if two integers 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
expectEqualUInt16
(
etInt16
id
,
const
char
*
msg
,
etUInt16
expected
,
etUInt16
actual
,
const
char
*
file
,
int
line
);
/**
* reports an error if two integers 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
expectEqualUInt32
(
etInt16
id
,
const
char
*
msg
,
etUInt32
expected
,
etUInt32
actual
,
const
char
*
file
,
int
line
);
/**
* reports an error if two floats 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 precision expected +/- precision defines the window for acceptance of an actual value
* \param file the file name with the test case
* \param line the line
*/
#ifdef ET_FLOAT32
void
expectEqualFloat32
(
etInt16
id
,
const
char
*
msg
,
etFloat32
expected
,
etFloat32
actual
,
etFloat32
precision
,
const
char
*
file
,
int
line
);
#endif
/**
* reports an error if two floats 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 precision expected +/- precision defines the window for acceptance of an actual value
* \param file the file name with the test case
* \param line the line
*/
#ifdef ET_FLOAT64
void
expectEqualFloat64
(
etInt16
id
,
const
char
*
msg
,
etFloat64
expected
,
etFloat64
actual
,
etFloat64
precision
,
const
char
*
file
,
int
line
);
#endif
/**
* reports an error if a value is not inside a range e.g. [-5.1, +3.0]
*
* \param id the test case id
* \param msg the result message
* \param min the lower limit (inclusive)
* \param max the upper limit (inclusive)
* \param actual the actual value
* \param file the file name with the test case
* \param line the line
*/
#ifdef ET_FLOAT32
void
expectRangeFloat32
(
etInt16
id
,
const
char
*
message
,
etFloat32
min
,
etFloat32
max
,
etFloat32
actual
,
const
char
*
file
,
int
line
)
;
#endif
/**
* reports an error if a value is not inside a range e.g. [-5.1, +3.0]
*
* \param id the test case id
* \param msg the result message
* \param min the lower limit (inclusive)
* \param max the upper limit (inclusive)
* \param actual the actual value
* \param file the file name with the test case
* \param line the line
*/
#ifdef ET_FLOAT64
void
expectRangeFloat64
(
etInt16
id
,
const
char
*
message
,
etFloat64
min
,
etFloat64
max
,
etFloat64
actual
,
const
char
*
file
,
int
line
)
;
#endif
/**
* reports an error if two pointers 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
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)
* are compared against the next value in the list and the list pointer is incremented
*
* \param id the test case id
* \param list the list of expected values
* \param size the size of the list
* \param file the file name with the test case
* \param line the line
*/
void
expectOrderStart
(
etInt16
id
,
const
etInt16
*
list
,
etInt16
size
,
const
char
*
file
,
int
line
);
/**
* reports an error if the identifier doesn't match the next value in the list
*
* \param id the test case id
* \param msg the result message
* \param identifier the expected next value
* \param file the file name with the test case
* \param line the line
*/
void
expectOrder
(
etInt16
id
,
const
char
*
msg
,
etInt16
identifier
,
const
char
*
file
,
int
line
);
/**
* reports an error if the identifier doesn't match the next value in the list which
* is expected to be the last one
*
* \param id the test case id
* \param msg the result message
* \param identifier the expected next value
* \param file the file name with the test case
* \param line the line
*/
void
expectOrderEnd
(
etInt16
id
,
const
char
*
msg
,
etInt16
identifier
,
const
char
*
file
,
int
line
);
ET_EXTERN_C_END
#endif
/* _ETUNIT_H_ */
...
...
runtime/org.eclipse.etrice.runtime.c/src/common/etUnit/etUnit2.c
0 → 100644
View file @
a01439a7
/*******************************************************************************
* Copyright (c) 2011 protos software gmbh (http://www.protos.de).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* CONTRIBUTORS:
* Thomas Schuetz (initial contribution)
*
*******************************************************************************/
#include "etUnit/etUnit2.h"
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <assert.h>
#include "debugging/etLogger.h"
#include "osal/etSema.h"
#include "runtime/etRuntime.h"
#include "helpers/etTimeHelpers.h"
/*** member variables */
/* file handling */
static
FILE
*
etUnit_reportfile
=
NULL
;
/* counters */
static
etInt16
etUnit_nextCaseId
;
static
etInt32
etUnit_errorCounter
;
static
etBool
etUnit_parallelTestCases
=
ET_FALSE
;
#define ETUNIT_MAX_PARALLEL_TEST_CASES 5
static
etBool
etUnit_testcaseSuccess
[
ETUNIT_MAX_PARALLEL_TEST_CASES
];
static
etBool
etUnit_testcaseOpen
[
ETUNIT_MAX_PARALLEL_TEST_CASES
];
#define ETUNIT_FAILURE_TEXT_LEN 256
/* time measuring */
static
etTime
etUnit_startTime
;
static
etTime
etUnit_lastTestCaseTime
;
/*
* Returns index to store current test case state
* - 'caseId' for parallel test cases
* - 0 for singleton test case
*/
static
etInt16
getParallelIndex
(
etInt16
caseId
)
{
etInt16
idx
=
(
etUnit_parallelTestCases
)
?
caseId
-
1
:
0
;
assert
(
idx
>=
0
&&
idx
<
ETUNIT_MAX_PARALLEL_TEST_CASES
);
return
idx
;
}
/* Lookup valid open test case id */
static
etInt16
getOpenTestCaseId
(
etInt16
id
)
{
etInt16
caseId
;
if
(
etUnit_parallelTestCases
)
{
// index is id of parallel test case
assert
(
id
>
0
);
caseId
=
id
;
}
else
{
// index is 0, return current open test case
assert
(
id
==
0
);
caseId
=
etUnit_nextCaseId
-
1
;
}
if
(
!
etUnit_testcaseOpen
[
getParallelIndex
(
caseId
)])
{
etLogger_logErrorF
(
"Test case was not opened"
);
}
return
caseId
;
}
/* order */
#define ETUNIT_ORDER_MAX 16
typedef
struct
OrderInfo
{
etInt16
id
;
etInt16
currentIndex
;
etInt16
size
;
const
etInt16
*
list
;
}
OrderInfo
;
static
OrderInfo
etUnit_orderInfo
[
ETUNIT_ORDER_MAX
];
static
OrderInfo
*
getOrderInfo
(
etInt16
id
)
{
etInt16
caseId
=
getOpenTestCaseId
(
id
);
for
(
int
i
=
0
;
i
<
ETUNIT_ORDER_MAX
;
++
i
)
if
(
etUnit_orderInfo
[
i
].
id
==
caseId
)
return
etUnit_orderInfo
+
i
;
return
NULL
;
}
/* float measuring */
#if defined (ET_FLOAT32) || defined (ET_FLOAT64)
#define ETUNIT_FLOAT
#ifdef ET_FLOAT64
typedef
etFloat64
etUnitFloat
;
#else
typedef
etFloat32
etUnitFloat
;
#endif
#endif
/* forward declarations of private functions */
static
void
expect_equal_int
(
etInt16
id
,
const
char
*
message
,
etInt32
expected
,
etInt32
actual
,
const
char
*
file
,
int
line
);
/* currently not used
static void expect_range_int(etInt16 id, const char* message, etInt32 min, etInt32 max, etInt32 actual, const char* file, int line);
*/
static
void
expect_equal_uint
(
etInt16
id
,
const
char
*
message
,
etUInt32
expected
,
etUInt32
actual
,
const
char
*
file
,
int
line
);
/* currently not used
static void expect_range_uint(etInt16 id, const char* message, etUInt32 min, etUInt32 max, etUInt32 actual, const char* file, int line);
*/
#ifdef ETUNIT_FLOAT
static
void
expect_equal_float
(
etInt16
id
,
const
char
*
message
,
etUnitFloat
expected
,
etUnitFloat
actual
,
etUnitFloat
precision
,
const
char
*
file
,
int
line
);
static
void
expect_range_float
(
etInt16
id
,
const
char
*
message
,
etUnitFloat
min
,
etUnitFloat
max
,
etUnitFloat
actual
,
const
char
*
file
,
int
line
);
#endif
static
void
etUnit_handleExpect
(
etInt16
id
,
etBool
result
,
const
char
*
trace
,
const
char
*
expected
,
const
char
*
actual
,
const
char
*
file
,
int
line
);
/* configuration functions */
void
etUnit_setParallelTestCases
(
etBool
enabled
)
{
etUnit_parallelTestCases
=
enabled
;
}
/* public functions */
void
etUnit_open
(
const
char
*
testResultPath
,
const
char
*
testFileName
)
{
etLogger_logInfoF
(
"************* TEST START (%s) **************"
,
testFileName
);
{
char
filename
[
ETUNIT_FAILURE_TEXT_LEN
];
if
(
testResultPath
!=
NULL
)
snprintf
(
filename
,
sizeof
(
filename
),
"%s/%s.etu"
,
testResultPath
,
testFileName
);
else
snprintf
(
filename
,
sizeof
(
filename
),
"%s.etu"
,
testFileName
);
/* init global data */
for
(
int
i
=
0
;
i
<
ETUNIT_ORDER_MAX
;
++
i
)
{
etUnit_orderInfo
[
i
].
id
=
0
;
}
for
(
int
i
=
0
;
i
<
ETUNIT_MAX_PARALLEL_TEST_CASES
;
++
i
)
{
etUnit_testcaseSuccess
[
i
]
=
ET_TRUE
;
etUnit_testcaseOpen
[
i
]
=
ET_FALSE
;
}
etUnit_errorCounter
=
0
;
etUnit_nextCaseId
=
1
;
if
(
etUnit_reportfile
==
NULL
)
{
etUnit_reportfile
=
etLogger_fopen
(
filename
,
"w+"
);
if
(
etUnit_reportfile
!=
NULL
)
{
etLogger_fprintf
(
etUnit_reportfile
,
"etUnit report
\n
"
);
}
else
{
etLogger_logErrorF
(
"Unable to open file %s"
,
filename
);
}
}
}
/* prepare time measurement */
getTimeFromTarget
(
&
etUnit_startTime
);
}
void
etUnit_close
(
void
)
{
etTime
endTime
;
if
(
etUnit_reportfile
!=
NULL
)
{
etLogger_fclose
(
etUnit_reportfile
);
etUnit_reportfile
=
NULL
;
}
getTimeFromTarget
(
&
endTime
);
etTimeHelpers_subtract
(
&
endTime
,
&
etUnit_startTime
);
etLogger_logInfoF
(
"Elapsed Time: %ld ms"
,
etTimeHelpers_convertToMSec
(
&
endTime
));
if
(
etUnit_errorCounter
==
0
)
etLogger_logInfoF
(
"Error Counter: %ld"
,
etUnit_errorCounter
);
else
etLogger_logErrorF
(
"Error Counter: %ld"
,
etUnit_errorCounter
);
etLogger_logInfoF
(
"************* TEST END **************"
);
}
void
etUnit_openTestSuite
(
const
char
*
testSuiteName
)
{
if
(
etUnit_reportfile
!=
NULL
)
{
etLogger_fprintf
(
etUnit_reportfile
,
"ts start: %s
\n
"
,
testSuiteName
);
}
}
void
etUnit_closeTestSuite
(
void
)
{
}
/* Opens new test case, if parallel is activated returns new test case id otherwise 0*/
etInt16
etUnit_openTestCase
(
const
char
*
testCaseName
)
{
if
(
etUnit_nextCaseId
>=
INT16_MAX
)
{
etLogger_logErrorF
(
"Too many test cases. Maximum number is %d"
,
INT16_MAX
);
exit
(
-
1
);
}
etInt16
caseId
=
etUnit_nextCaseId
++
;
etInt16
idx
=
getParallelIndex
(
caseId
);