Multi Process Testing framework

Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com>
This commit is contained in:
Martin Bremmer 2019-04-10 17:57:29 +02:00 committed by eboasson
parent 5a8197fa2b
commit 597ca25287
30 changed files with 2934 additions and 1 deletions

86
docs/dev/mpt_req.md Normal file
View file

@ -0,0 +1,86 @@
# Eclipse Cyclone DDS Multi Process Testing Requirements
This document present some requirements and considerations regarding the
[Multi Process Test Framework](multi_process_testing.md).
## Requirements
1.1) To test certain Cyclone DDS features, multiple processes running Cyclone
DDS are needed to force communication through the whole stack.
1.2) Should be buildable and runnable on platforms that support multiprocess
and filesystems including the ones used in the continues integration
context.
1.3) Results should be easily analyzable within the continues integration
context and when running locally. This can be done by reporting the
results in a standard format like xunit or cunit.
1.4) No processes must be left behind (f.i. deadlock in child process) when the
test finished (or timed out).
1.5) When running tests parallel, they should not interfere with each other.
1.6) Processes of the same test should be able to communicate (for settings,
syncing, etc).
1.7) It should be possible to analyze output/messages/tracing of the parent
and child processes to be able to draw a proper test conclusion.
## Considerations
2.1)
The files that actually contain the tests, should be focused on those tests.
This means that the process management and setting up (and usage of) IPC
between test processes should be handled by a test framework so that the
test files can remain as clean as possible.
2.2)
If possible, there shouldn't be a need for writing log files to a file system
when running the tests normally. It could be helpful, however, that these log
files are written when debugging related tests.
2.3)
Preferably, the DDS communication between the processes should not leave
localhost.
## Intentions
There doesn't seem to be a 3rd party test framework that addresses our
requirements in a satisfactory manner.
After some discussions with a few people (different people in different
meetings), it was decided to create our own framework and to go in the
following direction:
- Process creation/destruction/etc is (re)introduced in the ddsrt.<br>
[1.1/1.2]
- The files that contain the tests, should be easy to understand and focus on
the tests themselves.<br>
[2.1]
- Other files (generated or in the framework) should take care of the
intricacies of starting/monitoring the proper processes with the proper
settings.<br>
[1.4/1.6/2.1]
- To do this, a similar approach of the current CUnit build will be used;
CMake will scan the test files and create runners according to macros within
the test files.<br>
[2.1]
- The tests should be executed by CTest. For now this means that a proper
runner exit code for pass/fail is enough. We would like to add CUnit like
output in the future.<br>
[1.2/1.3]
- The Cyclone DDS API contains the possibility to monitor generated log traces.
This means we won't be needing to monitor actual log files. Just register a
log callback and go from there.<br>
[1.7/2.2]
- The framework should be able to generate unique domain ids and unique topic
names when necessary. That way, tests won't interfere with each other when
running in parallel.<br>
[1.5]

View file

@ -0,0 +1,86 @@
# Eclipse Cyclone DDS Multi Process Testing
Some features and functionalities of Cyclone DDS can only be tested when
there's communication between processes. Examples are durability, security,
etc. To really make sure that these kind of features work, extended tests
with multiple processes are needed.
This results in a number of [requirements](mpt_req.md).
There doesn't seem to be a 3rd party test framework that addresses our
requirements in a satisfactory manner. Therefore, it was decided to create
our own Multi Process Testing (MPT) framework.
This document will provide an overview of the MPT framework.
## Overview
An MPT application is basically divided into two components
1. Tests
2. Runner
The Tests are created by the developer. They don't need to worry about the
process management. They only have to provide process entry point(s), tests
and test processes that use these entry points. E.g.
```cpp
MPT_ProcessEntry(publisher, MPT_Args(int domain))
{
/* Publish a sample on the given domain. */
MPT_ASSERT(success, "publisher failed");
}
MPT_ProcessEntry(subscriber, MPT_Args(int domain))
{
/* Subscribe to a sample from the given domain. */
MPT_ASSERT(success, "subscriber failed");
}
MPT_TestProcess(helloworld, domain0, pub, publisher, MPT_ArgValues(0));
MPT_TestProcess(helloworld, domain0, sub, subscriber, MPT_ArgValues(0));
MPT_Test(helloworld, domain0);
MPT_TestProcess(helloworld, domain42, pub, publisher, MPT_ArgValues(42));
MPT_TestProcess(helloworld, domain42, sub, subscriber, MPT_ArgValues(42));
MPT_Test(helloworld, domain42);
```
There are more options, but see the
[usage test](../../src/mpt/tests/self/usage.c) for more elaborate examples.
CMake will identify suites, tests and processes depending on those MPT
macros.<br>
It'll use that to generate part of the MPT Runner. The Runner takes care
of starting test(s) and handling the process management.
The runner also takes care of preparing IPC between test processes so that
these processes can sync if they need to (NB, this will be a future extension).
#### Suite-Test-Process tree
A process is related to a test and that test is related to a suite.<br>
A suite can have multiple tests and tests can have multiple processes.<br>
This results in the following tree quite naturally.
<img src="pictures/mpt_tree.png" alt="Suite-Test-Process tree">
#### Test execution
There are 3 main ways to start an MPT application.
1. Without argument.<br>
All tests will be run.
2. With suite and/or test name patterns as arguments.<br>
A subset of tests will be run depending on the provided patterns.<br>
This allows ctest to execute single tests.
3. With a specific suite/test/process combination as arguments.<br>
An user will normally not use this.
The third option is used by the MPT application itself to start a specific
test related process. It does so by restarting itself with the proper
suite/test/process combination as indicated by the test. This results
in the following flow.
<img src="pictures/mpt_flow.png" alt="MPT application flow">

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -186,5 +186,11 @@ endif()
add_subdirectory(examples)
if (BUILD_TESTING)
# Multi Process Tests
add_subdirectory(mpt)
endif()
# Pull-in CPack and support for generating <Package>Config.cmake and packages.
include(Packaging)

View file

@ -107,7 +107,7 @@ typedef struct {
/** Function signature that log and trace callbacks must adhere too. */
typedef void(*dds_log_write_fn_t)(void *, const dds_log_data_t *);
extern uint32_t *const dds_log_mask;
DDS_EXPORT extern uint32_t *const dds_log_mask;
/**
* @brief Get currently enabled log and trace categories.

22
src/mpt/CMakeLists.txt Normal file
View file

@ -0,0 +1,22 @@
#
# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
# v. 1.0 which is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#
cmake_minimum_required(VERSION 3.7)
option(MPT_ENABLE_SELFTEST "Enable multi-process test-framework self test" OFF)
set(MPT_CMAKE "${CMAKE_CURRENT_SOURCE_DIR}/mpt/cmake/MPT.cmake")
set(MPT_SOURCE_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(MPT_BINARY_ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
add_subdirectory(mpt)
add_subdirectory(tests)

View file

@ -0,0 +1,17 @@
#
# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
# v. 1.0 which is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/include/mpt/resource.h.in" "${CMAKE_CURRENT_BINARY_DIR}/include/mpt/resource.h" @ONLY)

184
src/mpt/mpt/cmake/MPT.cmake Normal file
View file

@ -0,0 +1,184 @@
#
# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
# v. 1.0 which is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#
set(MPT_DIR "${CMAKE_CURRENT_LIST_DIR}/..")
function(parse_mpt_fixtures INPUT TEST_DISABLED TEST_TIMEOUT TEST_XFAIL)
set(s "[ \t\r\n]")
if(INPUT MATCHES ".disabled${s}*=${s}*([tT][rR][uU][eE]|[0-9]+)")
set(${TEST_DISABLED} "TRUE" PARENT_SCOPE)
else()
set(${TEST_DISABLED} "FALSE" PARENT_SCOPE)
endif()
if(INPUT MATCHES ".timeout${s}*=${s}*([0-9]+)")
set(${TEST_TIMEOUT} "${CMAKE_MATCH_1}" PARENT_SCOPE)
else()
set(${TEST_TIMEOUT} "0" PARENT_SCOPE)
endif()
if(INPUT MATCHES ".xfail${s}*=${s}*([tT][rR][uU][eE]|[0-9]+)")
set(${TEST_XFAIL} "true" PARENT_SCOPE)
else()
set(${TEST_XFAIL} "false" PARENT_SCOPE)
endif()
endfunction()
function(process_mpt_source_file SOURCE_FILE SUITES TESTS PROCESSES)
unset(tests)
unset(processes)
set(x "\\*")
set(s "[ \t\r\n]")
set(s_or_x "[ \t\r\n\\*]")
set(w "[_a-zA-Z0-9]")
set(ident_expr "(${s}*${w}+${s}*)")
# Very basic type recognition, only things that contain word characters and
# pointers are handled. And since this script does not actually have to
# compile any code, type checking is left to the compiler. An error (or
# warning) will be thrown if something is off.
#
# The "type" regular expression below will match things like:
# - <word> <word>
# - <word> *<word>
# - <word>* <word> *<word>
set(type_expr "(${s}*${w}+${x}*${s}+${s_or_x}*)+")
set(param_expr "${type_expr}${ident_expr}")
# Test fixture support (based on test fixtures as implemented in Criterion),
# to enable per-test (de)initializers, which is very different from
# per-suite (de)initializers, and timeouts.
#
# The following fixtures are supported:
# - init
# - fini
# - disabled
# - timeout
set(data_expr "(${s}*,${s}*\\.${w}+${s}*=[^,\\)]+)*")
file(READ "${SOURCE_FILE}" content)
# MPT_Test
set(test_expr "MPT_Test${s}*\\(${ident_expr},${ident_expr}${data_expr}\\)")
string(REGEX MATCHALL "${test_expr}" matches "${content}")
foreach(match ${matches})
string(REGEX REPLACE "${test_expr}" "\\1" suite "${match}")
string(REGEX REPLACE "${test_expr}" "\\2" test "${match}")
# Remove leading and trailing whitespace
string(STRIP "${suite}" suite)
string(STRIP "${test}" test)
# Extract fixtures that must be handled by CMake (.disabled and .timeout).
parse_mpt_fixtures("${match}" disabled timeout xfail)
list(APPEND tests "${suite}:${test}:${disabled}:${timeout}:${xfail}")
list(APPEND suites "${suite}")
endforeach()
# MPT_TestProcess
set(process_expr "MPT_TestProcess${s}*\\(${ident_expr},${ident_expr},${ident_expr}")
string(REGEX MATCHALL "${process_expr}" matches "${content}")
foreach(match ${matches})
string(REGEX REPLACE "${process_expr}" "\\1" suite "${match}")
string(REGEX REPLACE "${process_expr}" "\\2" test "${match}")
string(REGEX REPLACE "${process_expr}" "\\3" id "${match}")
# Remove leading and trailing whitespace
string(STRIP "${suite}" suite)
string(STRIP "${test}" test)
string(STRIP "${id}" id)
list(APPEND processes "${suite}:${test}:${id}")
endforeach()
set(${PROCESSES} ${processes} PARENT_SCOPE)
set(${TESTS} ${tests} PARENT_SCOPE)
set(${SUITES} ${suites} PARENT_SCOPE)
endfunction()
function(add_mpt_executable TARGET)
set(sources)
set(processes)
foreach(source ${ARGN})
if((EXISTS "${source}" OR EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${source}"))
unset(processes)
unset(tests)
unset(suites)
# Disable missing-field-initializers warnings as not having to specify
# every member, aka fixture, is intended behavior.
if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang" OR
${CMAKE_C_COMPILER_ID} STREQUAL "AppleClang" OR
${CMAKE_C_COMPILER_ID} STREQUAL "GNU")
set_property(
SOURCE "${source}"
PROPERTY COMPILE_FLAGS -Wno-missing-field-initializers)
endif()
process_mpt_source_file("${source}" suites tests processes)
foreach(suite ${suites})
set(addsuites "${addsuites}\n mpt_add_suite(mpt_suite_new(\"${suite}\"));")
endforeach()
foreach(testcase ${tests})
string(REPLACE ":" ";" testcase ${testcase})
list(GET testcase 0 suite)
list(GET testcase 1 test)
list(GET testcase 2 disabled)
list(GET testcase 3 timeout)
list(GET testcase 4 xfail)
set(addtests "${addtests}\n mpt_add_test(\"${suite}\", mpt_test_new(\"${test}\", ${timeout}, ${xfail}));")
# Add this test to ctest.
set(ctest "${TARGET}_${suite}_${test}")
add_test(
NAME ${ctest}
COMMAND ${TARGET} -s ${suite} -t ${test})
set_property(TEST ${ctest} PROPERTY TIMEOUT ${timeout})
set_property(TEST ${ctest} PROPERTY DISABLED ${disabled})
endforeach()
foreach(process ${processes})
string(REPLACE ":" ";" process ${process})
list(GET process 0 suite)
list(GET process 1 test)
list(GET process 2 id)
set(addprocs "${addprocs}\n mpt_add_process(\"${suite}\", \"${test}\", mpt_process_new(\"${id}\", MPT_TestProcessName(${suite}, ${test}, ${id})));")
set(procdecls "${procdecls}\nextern MPT_TestProcessDeclaration(${suite}, ${test}, ${id});")
endforeach()
list(APPEND sources "${source}")
endif()
endforeach()
configure_file(
"${MPT_DIR}/src/main.c.in" "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.c" @ONLY)
add_executable(
${TARGET} "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.c" ${sources})
target_include_directories(${TARGET} PRIVATE "${MPT_DIR}/include" "${MPT_BINARY_ROOT_DIR}/mpt/include")
target_link_libraries(${TARGET} PRIVATE ddsc)
# We need the 'expand environment variables' feature that is present in the
# 'util' module. However, it is currently not possible to properly link to
# that module on Windows. In the near future, the utils will be migrated to
# ddsrt, after which we automatically have access to expand_envvars.
# But until then, use this very ugly (but quick) hack to solve our immediate
# build issues.
target_include_directories(${TARGET} PRIVATE "${CMAKE_SOURCE_DIR}/util/include")
target_sources(${TARGET} PRIVATE "${CMAKE_SOURCE_DIR}/util/src/ut_expand_envvars.c")
endfunction()

View file

@ -0,0 +1,158 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef MPT_H_INCLUDED
#define MPT_H_INCLUDED
#include <stdio.h>
#include <stdbool.h>
#include "mpt/resource.h"
#include "mpt/private/mpt.h"
#include "dds/ddsrt/environ.h"
/* Environment name/value pair. */
typedef struct mpt_env_ {
const char *name;
const char *value;
} mpt_env_t;
/* Process entry argument definitions. */
#define MPT_Args(...) MPT_ProcessArgsSyntax, __VA_ARGS__
#define MPT_NoArgs() MPT_ProcessArgsSyntax
#define MPT_ArgValues(...) MPT_ProcessArgs, __VA_ARGS__
#define MPT_NoArgValues() MPT_ProcessArgs
/* Process entry definition. */
#define MPT_ProcessEntry(process, args)\
void MPT_ProcessEntryName(process)(args)
/* IPC functions. */
#define MPT_Send(str) mpt_ipc_send(MPT_ProcessArgs, str);
#define MPT_Wait(str) mpt_ipc_wait(MPT_ProcessArgs, str);
/*
* MPT_TestProcess generates a wrapper function that takes care of
* per-process initialization, environment settings,
* deinitialization and the actual process entry call.
*/
#define MPT_TestProcess(suite, test, name, process, args, ...) \
MPT_TestInitDeclaration(suite, test); \
MPT_TestFiniDeclaration(suite, test); \
MPT_TestProcessDeclaration(suite, test, name) \
{ \
mpt_data_t data = MPT_Fixture(__VA_ARGS__); \
\
/* Always export the process name. */ \
/* This can be used to generate unique log files fi. */ \
ddsrt_setenv("MPT_PROCESS_NAME", \
MPT_XSTR(MPT_TestProcessName(suite, test, name))); \
\
/* Initialize test related stuff first. */ \
MPT_TestInitName(suite, test)(); \
\
/* Pre-process initialization. */ \
mpt_export_env(data.environment); \
if (data.init != NULL) { \
data.init(); \
} \
\
/* Execute the actual process entry function. */ \
MPT_ProcessEntryName(process)(args); \
\
/* Teardown process and test. */ \
if (data.fini != NULL) { \
data.fini(); \
} \
MPT_TestFiniName(suite, test)(); \
}
/*
* MPT_Test generates wrapper functions that take care of
* per-test initialization, environment settings and
* deinitialization.
* This is also used by CMake to determine the ctest timeout
* and disabled settings.
*/
#define MPT_Test(suite, test, ...) \
MPT_TestInitDeclaration(suite, test) \
{ \
mpt_data_t data = MPT_Fixture(__VA_ARGS__); \
mpt_export_env(data.environment); \
if (data.init != NULL) { \
data.init(); \
} \
} \
MPT_TestFiniDeclaration(suite, test) \
{ \
mpt_data_t data = MPT_Fixture(__VA_ARGS__); \
if (data.fini != NULL) { \
data.fini(); \
} \
}
/*
* Test asserts.
* Printing is supported eg MPT_ASSERT_EQ(a, b, "foo: %s", bar")
*/
#define MPT_ASSERT(cond, ...) MPT__ASSERT__(cond, MPT_FATAL_NO, __VA_ARGS__)
#define MPT_ASSERT_FAIL(...) MPT_ASSERT(0, __VA_ARGS__)
#define MPT_ASSERT_EQ(value, expected, ...) MPT_ASSERT((value == expected), __VA_ARGS__)
#define MPT_ASSERT_NEQ(value, expected, ...) MPT_ASSERT((value != expected), __VA_ARGS__)
#define MPT_ASSERT_LEQ(value, expected, ...) MPT_ASSERT((value <= expected), __VA_ARGS__)
#define MPT_ASSERT_GEQ(value, expected, ...) MPT_ASSERT((value >= expected), __VA_ARGS__)
#define MPT_ASSERT_LT(value, expected, ...) MPT_ASSERT((value < expected), __VA_ARGS__)
#define MPT_ASSERT_GT(value, expected, ...) MPT_ASSERT((value > expected), __VA_ARGS__)
#define MPT_ASSERT_NULL(value, ...) MPT_ASSERT((value == NULL), __VA_ARGS__)
#define MPT_ASSERT_NOT_NULL(value, ...) MPT_ASSERT((value != NULL), __VA_ARGS__)
#define MPT_ASSERT_STR_EQ(value, expected, ...) MPT_ASSERT((MPT_STRCMP(value, expected, 1) == 0), __VA_ARGS__)
#define MPT_ASSERT_STR_NEQ(value, expected, ...) MPT_ASSERT((MPT_STRCMP(value, expected, 0) != 0), __VA_ARGS__)
#define MPT_ASSERT_STR_EMPTY(value, ...) MPT_ASSERT((MPT_STRLEN(value, 1) == 0), __VA_ARGS__)
#define MPT_ASSERT_STR_NOT_EMPTY(value, ...) MPT_ASSERT((MPT_STRLEN(value, 0) > 0), __VA_ARGS__)
/* Fatal just means that control is returned to the parent function. */
#define MPT_ASSERT_FATAL(cond, ...) MPT__ASSERT__(cond, MPT_FATAL_YES, __VA_ARGS__)
#define MPT_ASSERT_FATAL_FAIL(...) MPT_ASSERT_FATAL(0, __VA_ARGS__)
#define MPT_ASSERT_FATAL_EQ(value, expected, ...) MPT_ASSERT_FATAL((value == expected), __VA_ARGS__)
#define MPT_ASSERT_FATAL_NEQ(value, expected, ...) MPT_ASSERT_FATAL((value != expected), __VA_ARGS__)
#define MPT_ASSERT_FATAL_LEQ(value, expected, ...) MPT_ASSERT_FATAL((value <= expected), __VA_ARGS__)
#define MPT_ASSERT_FATAL_GEQ(value, expected, ...) MPT_ASSERT_FATAL((value >= expected), __VA_ARGS__)
#define MPT_ASSERT_FATAL_LT(value, expected, ...) MPT_ASSERT_FATAL((value < expected), __VA_ARGS__)
#define MPT_ASSERT_FATAL_GT(value, expected, ...) MPT_ASSERT_FATAL((value > expected), __VA_ARGS__)
#define MPT_ASSERT_FATAL_NULL(value, ...) MPT_ASSERT_FATAL((value == NULL), __VA_ARGS__)
#define MPT_ASSERT_FATAL_NOT_NULL(value, ...) MPT_ASSERT_FATAL((value != NULL), __VA_ARGS__)
#define MPT_ASSERT_FATAL_STR_EQ(value, expected, ...) MPT_ASSERT_FATAL((MPT_STRCMP(value, expected, 1) == 0), __VA_ARGS__)
#define MPT_ASSERT_FATAL_STR_NEQ(value, expected, ...) MPT_ASSERT_FATAL((MPT_STRCMP(value, expected, 0) != 0), __VA_ARGS__)
#define MPT_ASSERT_FATAL_STR_EMPTY(value, ...) MPT_ASSERT_FATAL((MPT_STRLEN(value, 1) == 0), __VA_ARGS__)
#define MPT_ASSERT_FATAL_STR_NOT_EMPTY(value, ...) MPT_ASSERT_FATAL((MPT_STRLEN(value, 0) > 0), __VA_ARGS__)
/* Helpful function to check for patterns in log callbacks. */
int mpt_patmatch(const char *pat, const char *str);
#endif /* MPT_H_INCLUDED */

View file

@ -0,0 +1,153 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef MPT_PRIVATE_H_INCLUDED
#define MPT_PRIVATE_H_INCLUDED
#include <stdio.h>
#include <string.h>
/*
* Just some helpful macros.
*/
#define MPT_XSTR(s) MPT_STR(s)
#define MPT_STR(s) #s
#define MPT_STRCMP(value, expected, err) \
(((value != NULL) && (expected != NULL)) ? strcmp(value, expected) : err)
#define MPT_STRLEN(value, err) \
((value != NULL) ? strlen(value) : err)
#define MPT_ProcessArgs mpt__args__, mpt__retval__
#define MPT_ProcessArgsSyntax \
const mpt_data_t *mpt__args__, mpt_retval_t *mpt__retval__
/*
* Name and declaration macros.
*/
#define MPT_ProcessEntryName(process) \
MPT_ProcessEntry__ ## process
#define MPT_TestInitName(suite, test) \
MPT_TestInit__##suite##_##test
#define MPT_TestInitDeclaration(suite, test) \
void MPT_TestInitName(suite, test)(void)
#define MPT_TestFiniName(suite, test) \
MPT_TestFini__##suite##_##test
#define MPT_TestFiniDeclaration(suite, test) \
void MPT_TestFiniName(suite, test)(void)
#define MPT_TestProcessName(suite, test, name) \
MPT_TestProcess__##suite##_##test##_##name
#define MPT_TestProcessDeclaration(suite, test, name) \
void MPT_TestProcessName(suite, test, name) (MPT_ProcessArgsSyntax)
/*
* MPT Assert impl.
*/
typedef enum {
MPT_SUCCESS = 0,
MPT_FAILURE
} mpt_retval_t;
#define MPT_FATAL_YES 1
#define MPT_FATAL_NO 0
#ifdef _WIN32
/* Microsoft Visual Studio does not expand __VA_ARGS__ correctly. */
#define MPT__ASSERT__(...) MPT__ASSERT____((__VA_ARGS__))
#define MPT__ASSERT____(tuple) MPT__ASSERT___ tuple
#else
#define MPT__ASSERT__(...) MPT__ASSERT___(__VA_ARGS__)
#endif /* _WIN32 */
#define MPT__ASSERT___(cond, fatal, ...) \
do { \
(void)mpt__args__; /* Satisfy compiler. */ \
if (!(cond)) { \
if (*mpt__retval__ == MPT_SUCCESS) { \
*mpt__retval__ = MPT_FAILURE; \
} \
printf("MPT_FAIL(%s, %d):\n", __FILE__, __LINE__); \
printf(__VA_ARGS__); \
printf("\n"); \
if (fatal == MPT_FATAL_YES) { \
return; \
} \
} \
} while(0)
/*
* MPT Fixture impl.
*/
struct mpt_env_;
typedef void(*mpt_init_func_t)(void);
typedef void(*mpt_fini_func_t)(void);
typedef struct {
/* Test and process fixtures. */
mpt_init_func_t init;
mpt_fini_func_t fini;
struct mpt_env_ *environment;
/* Test fixtures. */
bool disabled;
int timeout;
bool xfail;
/* IPC information. */
int todo;
} mpt_data_t;
/* Microsoft Visual Studio does not like empty struct initializers, i.e.
no fixtures are specified. To work around that issue MPT_Fixture inserts a
NULL initializer as fall back. */
#define MPT_Comma() ,
#define MPT_Reduce(one, ...) one
#ifdef _WIN32
/* Microsoft Visual Studio does not expand __VA_ARGS__ correctly. */
#define MPT_Fixture__(...) MPT_Fixture____((__VA_ARGS__))
#define MPT_Fixture____(tuple) MPT_Fixture___ tuple
#else
#define MPT_Fixture__(...) MPT_Fixture___(__VA_ARGS__)
#endif /* _WIN32 */
#define MPT_Fixture___(throw, away, value, ...) value
#define MPT_Fixture_(throwaway, ...) \
MPT_Fixture__(throwaway, ((mpt_data_t){ 0 }), ((mpt_data_t){ __VA_ARGS__ }))
#define MPT_Fixture(...) \
MPT_Fixture_( MPT_Comma MPT_Reduce(__VA_ARGS__,) (), __VA_ARGS__ )
/*
* MPT Support functions.
*/
void mpt_export_env(const struct mpt_env_ *env);
void mpt_ipc_send(MPT_ProcessArgsSyntax, const char *str);
void mpt_ipc_wait(MPT_ProcessArgsSyntax, const char *str);
#endif /* MPT_PRIVATE_H_INCLUDED */

View file

@ -0,0 +1,6 @@
#ifndef MPT_RESOURCE_H_INCLUDED
#define MPT_RESOURCE_H_INCLUDED
#define MPT_SOURCE_ROOT_DIR "@MPT_SOURCE_ROOT_DIR@"
#endif /* MPT_RESOURCE_H_INCLUDED */

551
src/mpt/mpt/src/main.c.in Normal file
View file

@ -0,0 +1,551 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "mpt/mpt.h"
#include "dds/ddsrt/heap.h"
#include "dds/ddsrt/process.h"
#include "dds/ddsrt/environ.h"
#include "dds/util/ut_expand_envvars.h"
#ifndef _WIN32
#include <sysexits.h>
#else
#define EX_USAGE (64)
#define EX_SOFTWARE (70)
#endif /* _WIN32 */
/************************************************
* Support functions.
************************************************/
int
mpt_patmatch(const char *pat, const char *str)
{
while (*pat) {
if (*pat == '?') {
/* any character will do */
if (*str++ == 0) {
return 0;
}
pat++;
} else if (*pat == '*') {
/* collapse a sequence of wildcards, requiring as many
characters in str as there are ?s in the sequence */
while (*pat == '*' || *pat == '?') {
if (*pat == '?' && *str++ == 0) {
return 0;
}
pat++;
}
/* try matching on all positions where str matches pat */
while (*str) {
if (*str == *pat && mpt_patmatch(pat+1, str+1)) {
return 1;
}
str++;
}
return *pat == 0;
} else {
/* only an exact match */
if (*str++ != *pat++) {
return 0;
}
}
}
return *str == 0;
}
void
mpt_export_env(const mpt_env_t *env)
{
if (env) {
while ((env->name != NULL) && (env->value != NULL)) {
char *expanded = ut_expand_envvars(env->value);
ddsrt_setenv(env->name, expanded);
ddsrt_free(expanded);
env++;
}
}
}
void
mpt_ipc_send(MPT_ProcessArgsSyntax, const char *str)
{
(void)str;
(void)mpt__args__;
/* TODO: implement. */
MPT_ASSERT(0, "mpt_ipc_send not implemented");
}
void
mpt_ipc_wait(MPT_ProcessArgsSyntax, const char *str)
{
(void)str;
(void)mpt__args__;
/* TODO: implement. */
MPT_ASSERT(0, "mpt_ipc_wait not implemented");
}
/************************************************
* Processes.
************************************************/
@procdecls@
typedef void(*mpt_func_proc_t)(
const mpt_data_t *mpt__args__, mpt_retval_t *mpt__retval__);
typedef struct mpt_process_ {
const char* name;
ddsrt_pid_t pid;
mpt_func_proc_t process;
struct mpt_process_ *next;
} mpt_process_t;
static mpt_process_t*
mpt_process_new(const char* name, mpt_func_proc_t process)
{
mpt_process_t *proc;
proc = ddsrt_malloc(sizeof(mpt_process_t));
proc->pid = 0;
proc->name = name;
proc->process = process;
proc->next = NULL;
return proc;
}
static void
mpt_process_freelist(mpt_process_t *proc)
{
if (proc) {
mpt_process_freelist(proc->next);
if (proc->pid != 0) {
printf("Process %s kill(%d)\n", proc->name, (int)proc->pid);
ddsrt_proc_kill(proc->pid);
}
ddsrt_free(proc);
}
}
/************************************************
* Tests.
************************************************/
typedef struct mpt_test_ {
const char* name;
bool xfail;
dds_duration_t timeout;
mpt_process_t *procs;
struct mpt_test_ *next;
} mpt_test_t;
static mpt_test_t*
mpt_test_new(const char* name, int secs, bool xf)
{
mpt_test_t *test;
test = ddsrt_malloc(sizeof(mpt_test_t));
test->procs = NULL;
test->name = name;
test->xfail = xf;
/* This test will stop after a given timeout. However, when running in
* ctest, we'd like to use the ctest provided timeout functionality.
* So, make sure that the 'manual' timeout takes longer than the ctest
* timeout. */
if (secs == 0) {
test->timeout = DDS_SECS(1600);
} else {
test->timeout = DDS_SECS(secs * 2);
}
return test;
}
static void
mpt_test_freelist(mpt_test_t *test)
{
if (test) {
mpt_process_freelist(test->procs);
mpt_test_freelist(test->next);
}
ddsrt_free(test);
}
static void
mpt_test_add_process(mpt_test_t *test, mpt_process_t *proc)
{
/* Prepend */
proc->next = test->procs;
test->procs = proc;
}
/************************************************
* Suites.
************************************************/
typedef struct mpt_suite_ {
const char* name;
mpt_test_t *tests;
struct mpt_suite_ *next;
} mpt_suite_t;
static mpt_suite_t*
mpt_suite_new(const char* name)
{
mpt_suite_t *suite;
suite = ddsrt_malloc(sizeof(mpt_suite_t));
suite->tests = NULL;
suite->name = name;
return suite;
}
static void
mpt_suite_freelist(mpt_suite_t *suite)
{
if (suite) {
mpt_test_freelist(suite->tests);
mpt_suite_freelist(suite->next);
}
ddsrt_free(suite);
}
static void
mpt_suite_add_test(mpt_suite_t *suite, mpt_test_t *test)
{
/* Prepend */
test->next = suite->tests;
suite->tests = test;
}
static mpt_test_t*
mpt_suite_find_test(
mpt_suite_t *suite, const char *tname)
{
mpt_test_t *found = suite->tests;
while (found) {
if (mpt_patmatch(tname, found->name)) {
break;
}
found = found->next;
}
return found;
}
/************************************************
* Root.
************************************************/
mpt_suite_t *root = NULL;
static void
mpt_add_suite(mpt_suite_t *suite)
{
/* Prepend */
suite->next = root;
root = suite;
}
static mpt_suite_t*
mpt_find_suite(const char *sname)
{
mpt_suite_t *found = root;
while (found) {
if (mpt_patmatch(sname, found->name)) {
break;
}
found = found->next;
}
return found;
}
static void
mpt_add_test(const char *sname, mpt_test_t *test)
{
mpt_suite_t *suite = mpt_find_suite(sname);
assert(suite);
mpt_suite_add_test(suite, test);
}
static void
mpt_add_process(const char *sname, const char *tname, mpt_process_t *proc)
{
mpt_suite_t *suite = mpt_find_suite(sname);
mpt_test_t *test = mpt_suite_find_test(suite, tname);
assert(suite);
assert(test);
mpt_test_add_process(test, proc);
}
static void
mpt_free(void)
{
mpt_suite_freelist(root);
root = NULL;
}
/************************************************
* Runner.
************************************************/
static int
mpt_run_test(const char *exe, mpt_suite_t *suite, mpt_test_t *test)
{
int result = EXIT_SUCCESS;
mpt_process_t *proc;
dds_retcode_t retcode;
char *argv[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
argv[0] = "-s";
argv[1] = (char*)suite->name;
argv[2] = "-t";
argv[3] = (char*)test->name;
/* Start the processes. */
proc = test->procs;
while ((proc) && (result == EXIT_SUCCESS)) {
if (proc == test->procs) {
printf("\n\n");
printf("=====================================================\n");
printf("Suite: %s\n", suite->name);
printf("Test: %s\n", test->name);
printf("=====================================================\n");
}
argv[4] = "-p";
argv[5] = (char*)proc->name;
retcode = ddsrt_proc_create(exe, argv, &proc->pid);
if (retcode != DDS_RETCODE_OK) {
printf("Start %s::%s::%s failed\n", suite->name, test->name, proc->name);
proc->pid = 0;
result = EXIT_FAILURE;
}
proc = proc->next;
}
/* Wait for the processes. */
retcode = DDS_RETCODE_OK;
while ((result == EXIT_SUCCESS) && (retcode == DDS_RETCODE_OK)) {
int32_t status;
ddsrt_pid_t pid;
/* A second/third/etc wait will restart the timeout.
* This means that the end timeout can take longer than the requested
* test timeout. However, that's good enough for our purpose. */
retcode = ddsrt_proc_waitpids(test->timeout, &pid, &status);
if (retcode == DDS_RETCODE_OK) {
proc = test->procs;
while (proc) {
if (proc->pid == pid) {
break;
}
proc = proc->next;
}
if (proc) {
proc->pid = 0;
if (status != 0) {
printf("Process %s::%s::%s failed (%d)\n", suite->name, test->name, proc->name, status);
result = EXIT_FAILURE;
}
} else {
printf("Wait for processes of %s::%s return unknown pid %d\n", suite->name, test->name, (int)pid);
result = EXIT_FAILURE;
}
} else if (retcode != DDS_RETCODE_NOT_FOUND) {
printf("Wait for processes of %s::%s failed (%d)\n", suite->name, test->name, (int)retcode);
result = EXIT_FAILURE;
}
}
/* Be sure to kill all remaining processes when needed. */
if (result != EXIT_SUCCESS) {
proc = test->procs;
while (proc) {
if (proc->pid != 0) {
printf("Process %s::%s::%s kill(%d)\n", suite->name, test->name, proc->name, (int)proc->pid);
ddsrt_proc_kill(proc->pid);
ddsrt_proc_waitpid(proc->pid, DDS_SECS(10), NULL);
proc->pid = 0;
}
proc = proc->next;
}
}
/* Revert result when we expect the test to have failed. */
if (test->xfail) {
result = ((result == EXIT_SUCCESS) ? EXIT_FAILURE : EXIT_SUCCESS);
}
return result;
}
static int
mpt_run_tests(const char *exe, const char *spattern, const char *tpattern)
{
int result = EXIT_SUCCESS;
mpt_suite_t *suite = root;
while (suite) {
if (mpt_patmatch(spattern, suite->name)) {
mpt_test_t *test = suite->tests;
while (test) {
if (mpt_patmatch(tpattern, test->name)) {
int run = mpt_run_test(exe, suite, test);
if (run != EXIT_SUCCESS) {
result = run;
}
}
test = test->next;
}
}
suite = suite->next;
}
return result;
}
static int
mpt_run_proc(mpt_process_t *proc)
{
mpt_retval_t retval = MPT_SUCCESS;
mpt_data_t args;
proc->process(&args, &retval);
return (retval == MPT_SUCCESS) ? EXIT_SUCCESS : EXIT_FAILURE;
}
static int
mpt_run_procs(const char *spattern, const char *tpattern, const char *ppattern)
{
int result = EXIT_SUCCESS;
mpt_suite_t *suite = root;
while (suite) {
if (mpt_patmatch(spattern, suite->name)) {
mpt_test_t *test = suite->tests;
while (test) {
if (mpt_patmatch(tpattern, test->name)) {
mpt_process_t *proc = test->procs;
while (proc) {
if (mpt_patmatch(ppattern, proc->name)) {
int run = mpt_run_proc(proc);
if (run != EXIT_SUCCESS) {
result = run;
}
}
proc = proc->next;
}
}
test = test->next;
}
}
suite = suite->next;
}
return result;
}
/************************************************
* Main functionality.
************************************************/
static struct {
bool print_help;
const char *suite;
const char *test;
const char *process;
} opts = {
false,
"*",
"*",
NULL
};
static int parse_options(int argc, char *argv[])
{
int err = 0;
for (int i = 1; err == 0 && i < argc; i++) {
switch ((argv[i][0] == '-') ? argv[i][1] : 0) {
case 'h':
opts.print_help = true;
break;
case 's':
if ((i+1) < argc) {
opts.suite = argv[++i];
break;
}
/* FALLS THROUGH */
case 't':
if ((i+1) < argc) {
opts.test = argv[++i];
break;
}
/* FALLS THROUGH */
case 'p':
if ((i+1) < argc) {
opts.process = argv[++i];
break;
}
/* FALLS THROUGH */
default:
err = 1;
break;
}
}
return err;
}
static void usage(const char *name)
{
fprintf(stderr, "Usage: %s OPTIONS\n", name);
fprintf(stderr, "Try '%s -h' for more information\n", name);
}
static void help(const char *name)
{
printf("Usage: %s [OPTIONS]\n", name);
printf("\n");
printf("Possible options:\n");
printf(" -h display this help and exit\n");
printf(" -s PATTERN run only tests in suites matching pattern\n");
printf(" -t PATTERN run only test matching pattern\n");
printf(" -p PROCESS run only process matching pattern\n");
printf("\n");
printf("Exit codes:\n");
printf(" %-2d Successful termination\n", EXIT_SUCCESS);
printf(" %-2d One or more failing test cases\n", EXIT_FAILURE);
printf(" %-2d Command line usage error\n", EX_USAGE);
printf(" %-2d Internal software error\n", EX_SOFTWARE);
}
int main(int argc, char *argv[])
{
int result = EXIT_SUCCESS;
if (parse_options(argc, argv) != 0) {
usage(argv[0]);
return EX_USAGE;
} else if (opts.print_help) {
help(argv[0]);
return result;
}
atexit(mpt_free);
@addsuites@
@addtests@
@addprocs@
if (opts.process == NULL) {
/* Run test(s). */
result = mpt_run_tests(argv[0], opts.suite, opts.test);
} else {
/* Run process(es). */
result = mpt_run_procs(opts.suite, opts.test, opts.process);
}
return result;
}

View file

@ -0,0 +1,19 @@
#
# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
# v. 1.0 which is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#
cmake_minimum_required(VERSION 3.7)
if(MPT_ENABLE_SELFTEST)
add_subdirectory(self)
endif()
add_subdirectory(basic)

View file

@ -0,0 +1,23 @@
#
# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
# v. 1.0 which is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#
include(${MPT_CMAKE})
set(sources
"procs/hello.c"
"helloworld.c"
"multi.c")
add_mpt_executable(mpt_basic ${sources})
idlc_generate(mpt_basic_helloworlddata_lib "procs/helloworlddata.idl")
target_link_libraries(mpt_basic PRIVATE mpt_basic_helloworlddata_lib)

View file

@ -0,0 +1,30 @@
<!--
Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0 which is available at
http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
v. 1.0 which is available at
http://www.eclipse.org/org/documents/edl-v10.php.
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
-->
<CycloneDDS>
<Domain>
<Id>any</Id>
</Domain>
<DDSI2E>
<General>
<NetworkInterfaceAddress>auto</NetworkInterfaceAddress>
<AllowMulticast>true</AllowMulticast>
<EnableMulticastLoopback>true</EnableMulticastLoopback>
</General>
<Compatibility>
<StandardsConformance>lax</StandardsConformance>
</Compatibility>
<!--Tracing>
<Verbosity>finest</Verbosity>
<OutputFile>ddsi_${MPT_PROCESS_NAME}.log</OutputFile>
</Tracing-->
</DDSI2E>
</CycloneDDS>

View file

@ -0,0 +1,30 @@
<!--
Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0 which is available at
http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
v. 1.0 which is available at
http://www.eclipse.org/org/documents/edl-v10.php.
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
-->
<CycloneDDS>
<Domain>
<Id>${DOMAIN_ID}</Id>
</Domain>
<DDSI2E>
<General>
<NetworkInterfaceAddress>auto</NetworkInterfaceAddress>
<AllowMulticast>true</AllowMulticast>
<EnableMulticastLoopback>true</EnableMulticastLoopback>
</General>
<Compatibility>
<StandardsConformance>lax</StandardsConformance>
</Compatibility>
<!--Tracing>
<Verbosity>finest</Verbosity>
<OutputFile>ddsi_${MPT_PROCESS_NAME}.log</OutputFile>
</Tracing-->
</DDSI2E>
</CycloneDDS>

View file

@ -0,0 +1,63 @@
#include "dds/dds.h"
#include "mpt/mpt.h"
#include "mpt/resource.h" /* MPT_SOURCE_ROOT_DIR */
#include "procs/hello.h" /* publisher and subscriber entry points. */
/*
* Tests to check simple communication between a publisher and subscriber.
* The published text should be received by the subscriber.
*/
/* Environments */
static mpt_env_t environment_any[] = {
{ "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/basic/etc" },
{ "CYCLONEDDS_URI", "file://${ETC_DIR}/config_any.xml" },
{ NULL, NULL }
};
static mpt_env_t environment_42[] = {
{ "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/basic/etc" },
{ "DOMAIN_ID", "42" },
{ "CYCLONEDDS_URI", "file://${ETC_DIR}/config_specific.xml" },
{ NULL, NULL }
};
/**********************************************************************
* No CYCLONEDDS_URI set.
**********************************************************************/
#define TEST_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "hello_def", 1, "No environment set")
MPT_TestProcess(helloworld, default, pub, hello_publisher, TEST_ARGS);
MPT_TestProcess(helloworld, default, sub, hello_subscriber, TEST_ARGS);
MPT_Test(helloworld, default, .init=hello_init, .fini=hello_fini);
#undef TEST_ARGS
/**********************************************************************
* Config domain is any. Test domain is default.
**********************************************************************/
#define TEST_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "hello_any", 1, "Some nice text over any domain")
MPT_TestProcess(helloworld, domain_any, pub, hello_publisher, TEST_ARGS);
MPT_TestProcess(helloworld, domain_any, sub, hello_subscriber, TEST_ARGS);
MPT_Test(helloworld, domain_any, .init=hello_init, .fini=hello_fini, .environment=environment_any);
#undef TEST_ARGS
/**********************************************************************
* Pub: Config domain is any. Test domain is 42.
* Sub: Config domain is 42 (through DOMAIN_ID env). Test domain is default.
**********************************************************************/
#define TEST_PUB_ARGS MPT_ArgValues(42, "hello_42", 1, "Now domain 42 is used")
#define TEST_SUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "hello_42", 1, "Now domain 42 is used")
MPT_TestProcess(helloworld, domain_42, pub, hello_publisher, TEST_PUB_ARGS, .environment=environment_any);
MPT_TestProcess(helloworld, domain_42, sub, hello_subscriber, TEST_SUB_ARGS, .environment=environment_42);
MPT_Test(helloworld, domain_42, .init=hello_init, .fini=hello_fini);
#undef TEST_SUB_ARGS
#undef TEST_PUB_ARGS

View file

@ -0,0 +1,50 @@
#include "mpt/mpt.h"
#include "procs/hello.h"
/*
* Tests to check communication between multiple publisher(s) and subscriber(s).
*/
/*
* The publisher expects 2 publication matched.
* The subscribers expect 1 sample each.
*/
#define TEST_PUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubsubsub", 2, "pubsubsub")
#define TEST_SUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubsubsub", 1, "pubsubsub")
MPT_TestProcess(multi, pubsubsub, pub, hello_publisher, TEST_PUB_ARGS);
MPT_TestProcess(multi, pubsubsub, sub1, hello_subscriber, TEST_SUB_ARGS);
MPT_TestProcess(multi, pubsubsub, sub2, hello_subscriber, TEST_SUB_ARGS);
MPT_Test(multi, pubsubsub, .init=hello_init, .fini=hello_fini);
#undef TEST_SUB_ARGS
#undef TEST_PUB_ARGS
/*
* The publishers expect 1 publication matched each.
* The subscriber expects 2 samples.
*/
#define TEST_PUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubpubsub", 1, "pubpubsub")
#define TEST_SUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubpubsub", 2, "pubpubsub")
MPT_TestProcess(multi, pubpubsub, pub1, hello_publisher, TEST_PUB_ARGS);
MPT_TestProcess(multi, pubpubsub, pub2, hello_publisher, TEST_PUB_ARGS);
MPT_TestProcess(multi, pubpubsub, sub, hello_subscriber, TEST_SUB_ARGS);
MPT_Test(multi, pubpubsub, .init=hello_init, .fini=hello_fini);
#undef TEST_SUB_ARGS
#undef TEST_PUB_ARGS
/*
* The publishers expect 2 publication matched each.
* The subscribers expect 2 samples each.
*/
#define TEST_PUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubpubsubsub", 2, "pubpubsubsub")
#define TEST_SUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubpubsubsub", 2, "pubpubsubsub")
MPT_TestProcess(multi, pubpubsubsub, pub1, hello_publisher, TEST_PUB_ARGS);
MPT_TestProcess(multi, pubpubsubsub, pub2, hello_publisher, TEST_PUB_ARGS);
MPT_TestProcess(multi, pubpubsubsub, sub1, hello_subscriber, TEST_SUB_ARGS);
MPT_TestProcess(multi, pubpubsubsub, sub2, hello_subscriber, TEST_SUB_ARGS);
MPT_Test(multi, pubpubsubsub, .init=hello_init, .fini=hello_fini);
#undef TEST_SUB_ARGS
#undef TEST_PUB_ARGS

View file

@ -0,0 +1,239 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "mpt/mpt.h"
#include "dds/dds.h"
#include "helloworlddata.h"
#include "dds/ddsrt/time.h"
#include "dds/ddsrt/strtol.h"
#include "dds/ddsrt/process.h"
#include "dds/ddsrt/environ.h"
#include "dds/ddsrt/cdtors.h"
#include "dds/ddsrt/sync.h"
/* An array of one message (aka sample in dds terms) will be used. */
#define MAX_SAMPLES 1
static int g_publication_matched_count = 0;
static ddsrt_mutex_t g_mutex;
static ddsrt_cond_t g_cond;
static void
publication_matched_cb(
dds_entity_t writer,
const dds_publication_matched_status_t status,
void* arg)
{
(void)arg;
(void)writer;
ddsrt_mutex_lock(&g_mutex);
g_publication_matched_count = (int)status.current_count;
ddsrt_cond_broadcast(&g_cond);
ddsrt_mutex_unlock(&g_mutex);
}
static void
data_available_cb(
dds_entity_t reader,
void* arg)
{
(void)arg;
(void)reader;
ddsrt_mutex_lock(&g_mutex);
ddsrt_cond_broadcast(&g_cond);
ddsrt_mutex_unlock(&g_mutex);
}
void
hello_init(void)
{
ddsrt_init();
ddsrt_mutex_init(&g_mutex);
ddsrt_cond_init(&g_cond);
}
void
hello_fini(void)
{
ddsrt_cond_destroy(&g_cond);
ddsrt_mutex_destroy(&g_mutex);
ddsrt_fini();
}
/*
* The HelloWorld publisher.
* It waits for a publication matched, and then writes a sample.
* It quits when the publication matched has been reset again.
*/
MPT_ProcessEntry(hello_publisher,
MPT_Args(dds_domainid_t domainid,
const char *topic_name,
int sub_cnt,
const char *text))
{
HelloWorldData_Msg msg;
dds_listener_t *listener;
dds_entity_t participant;
dds_entity_t topic;
dds_entity_t writer;
dds_return_t rc;
dds_qos_t *qos;
int id = (int)ddsrt_getpid();
assert(topic_name);
assert(text);
printf("=== [Publisher(%d)] Start(%d) ...\n", id, domainid);
/*
* A reliable volatile sample, written after publication matched, can still
* be lost when the subscriber wasn't able to match its subscription yet.
* Use transient_local reliable to make sure the sample is received.
*/
qos = dds_create_qos();
dds_qset_durability(qos, DDS_DURABILITY_TRANSIENT_LOCAL);
dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_SECS(10));
/* Use listener to get number of publications matched. */
listener = dds_create_listener(NULL);
MPT_ASSERT_FATAL_NOT_NULL(listener, "Could not create listener");
dds_lset_publication_matched(listener, publication_matched_cb);
/* Create a Writer. */
participant = dds_create_participant (domainid, NULL, NULL);
MPT_ASSERT_FATAL_GT(participant, 0, "Could not create participant: %s\n", dds_strretcode(-participant));
topic = dds_create_topic (
participant, &HelloWorldData_Msg_desc, topic_name, qos, NULL);
MPT_ASSERT_FATAL_GT(topic, 0, "Could not create topic: %s\n", dds_strretcode(-topic));
writer = dds_create_writer (participant, topic, qos, listener);
MPT_ASSERT_FATAL_GT(writer, 0, "Could not create writer: %s\n", dds_strretcode(-writer));
/* Wait for expected nr of subscriber(s). */
ddsrt_mutex_lock(&g_mutex);
while (g_publication_matched_count != sub_cnt) {
ddsrt_cond_waitfor(&g_cond, &g_mutex, DDS_INFINITY);
}
ddsrt_mutex_unlock(&g_mutex);
/* Write sample. */
msg.userID = (int32_t)id;
msg.message = (char*)text;
printf("=== [Publisher(%d)] Send: { %d, %s }\n", id, msg.userID, msg.message);
rc = dds_write (writer, &msg);
MPT_ASSERT_EQ(rc, DDS_RETCODE_OK, "Could not write sample\n");
/* Wait for subscriber(s) to have finished. */
ddsrt_mutex_lock(&g_mutex);
while (g_publication_matched_count != 0) {
ddsrt_cond_waitfor(&g_cond, &g_mutex, DDS_INFINITY);
}
ddsrt_mutex_unlock(&g_mutex);
rc = dds_delete (participant);
MPT_ASSERT_EQ(rc, DDS_RETCODE_OK, "Teardown failed\n");
dds_delete_listener(listener);
dds_delete_qos(qos);
printf("=== [Publisher(%d)] Done\n", id);
}
/*
* The HelloWorld subscriber.
* It waits for sample(s) and checks the content.
*/
MPT_ProcessEntry(hello_subscriber,
MPT_Args(dds_domainid_t domainid,
const char *topic_name,
int sample_cnt,
const char *text))
{
HelloWorldData_Msg *msg;
void *samples[MAX_SAMPLES];
dds_sample_info_t infos[MAX_SAMPLES];
dds_listener_t *listener;
dds_entity_t participant;
dds_entity_t topic;
dds_entity_t reader;
dds_return_t rc;
dds_qos_t *qos;
int recv_cnt;
int id = (int)ddsrt_getpid();
assert(topic_name);
assert(text);
printf("--- [Subscriber(%d)] Start(%d) ...\n", id, domainid);
/*
* A reliable volatile sample, written after publication matched, can still
* be lost when the subscriber wasn't able to match its subscription yet.
* Use transient_local reliable to make sure the sample is received.
*/
qos = dds_create_qos();
dds_qset_durability(qos, DDS_DURABILITY_TRANSIENT_LOCAL);
dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_SECS(10));
/* Use listener to get data available trigger. */
listener = dds_create_listener(NULL);
MPT_ASSERT_FATAL_NOT_NULL(listener, "Could not create listener");
dds_lset_data_available(listener, data_available_cb);
/* Create a Reader. */
participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
MPT_ASSERT_FATAL_GT(participant, 0, "Could not create participant: %s\n", dds_strretcode(-participant));
topic = dds_create_topic (
participant, &HelloWorldData_Msg_desc, topic_name, qos, NULL);
MPT_ASSERT_FATAL_GT(topic, 0, "Could not create topic: %s\n", dds_strretcode(-topic));
reader = dds_create_reader (participant, topic, qos, listener);
MPT_ASSERT_FATAL_GT(reader, 0, "Could not create reader: %s\n", dds_strretcode(-reader));
printf("--- [Subscriber(%d)] Waiting for %d sample(s) ...\n", id, sample_cnt);
/* Initialize sample buffer, by pointing the void pointer within
* the buffer array to a valid sample memory location. */
samples[0] = HelloWorldData_Msg__alloc ();
/* Wait until expected nr of samples have been taken. */
ddsrt_mutex_lock(&g_mutex);
recv_cnt = 0;
while (recv_cnt < sample_cnt) {
/* Use a take with mask to work around the #146 issue. */
rc = dds_take_mask(reader, samples, infos, MAX_SAMPLES, MAX_SAMPLES, DDS_NEW_VIEW_STATE);
MPT_ASSERT_GEQ(rc, 0, "Could not read: %s\n", dds_strretcode(-rc));
/* Check if we read some data and it is valid. */
if ((rc > 0) && (infos[0].valid_data)) {
/* Print Message. */
msg = (HelloWorldData_Msg*)samples[0];
printf("--- [Subscriber(%d)] Received: { %d, %s }\n", id,
msg->userID, msg->message);
MPT_ASSERT_STR_EQ(msg->message, text,
"Messages do not match: \"%s\" vs \"%s\"\n",
msg->message, text);
recv_cnt++;
} else {
ddsrt_cond_waitfor(&g_cond, &g_mutex, DDS_INFINITY);
}
}
ddsrt_mutex_unlock(&g_mutex);
/* Free the data location. */
HelloWorldData_Msg_free (samples[0], DDS_FREE_ALL);
rc = dds_delete (participant);
MPT_ASSERT_EQ(rc, DDS_RETCODE_OK, "Teardown failed\n");
dds_delete_listener(listener);
dds_delete_qos(qos);
printf("--- [Subscriber(%d)] Done\n", id);
}

View file

@ -0,0 +1,52 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
/** @file
*
* @brief DDS C Communication Status API
*
* This header file defines the public API of the Communication Status in the
* Eclipse Cyclone DDS C language binding.
*/
#ifndef MPT_BASIC_PROCS_HELLO_H
#define MPT_BASIC_PROCS_HELLO_H
#include <stdio.h>
#include <string.h>
#include "dds/dds.h"
#include "mpt/mpt.h"
#if defined (__cplusplus)
extern "C" {
#endif
void hello_init(void);
void hello_fini(void);
MPT_ProcessEntry(hello_publisher,
MPT_Args(dds_domainid_t domainid,
const char *topic_name,
int sub_cnt,
const char *text));
MPT_ProcessEntry(hello_subscriber,
MPT_Args(dds_domainid_t domainid,
const char *topic_name,
int sample_cnt,
const char *text));
#if defined (__cplusplus)
}
#endif
#endif /* MPT_BASIC_PROCS_HELLO_H */

View file

@ -0,0 +1,9 @@
module HelloWorldData
{
struct Msg
{
long userID;
string message;
};
#pragma keylist Msg userID
};

View file

@ -0,0 +1,25 @@
#
# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
# v. 1.0 which is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#
include(${MPT_CMAKE})
message(STATUS "MPT selftest enabled: some test will fail deliberately")
set(sources
"asserts.c"
"environments.c"
"fixtures.c"
"ipc.c"
"resources.c"
"usage.c")
add_mpt_executable(mpt_self ${sources})

View file

@ -0,0 +1,711 @@
#include <stdio.h>
#include <assert.h>
#include "mpt/mpt.h"
#include "dds/ddsrt/time.h"
static int dummy;
/************************************************************
* Test MPT_ASSERT
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT, MPT_Args(const char *exp, int cond))
{
assert(exp);
MPT_ASSERT(cond, "MPT_ASSERT(%d), 1st, expect: %s", cond, exp);
MPT_ASSERT(cond, "MPT_ASSERT(%d), 2nd, expect: %s", cond, exp);
}
MPT_TestProcess(MPT_ASSERT, pass, id, proc_MPT_ASSERT, MPT_ArgValues("PASS", 1));
MPT_TestProcess(MPT_ASSERT, fail, id, proc_MPT_ASSERT, MPT_ArgValues("FAIL", 0));
MPT_Test(MPT_ASSERT, pass, .xfail=false);
MPT_Test(MPT_ASSERT, fail, .xfail=true);
/************************************************************
* Test MPT_ASSERT_FAIL
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_FAIL, MPT_NoArgs())
{
MPT_ASSERT_FAIL("MPT_ASSERT_FAIL(), 1st, expect a fail, always");
MPT_ASSERT_FAIL("MPT_ASSERT_FAIL(), 2nd, expect a fail, always");
}
MPT_TestProcess(MPT_ASSERT_FAIL, call, id, proc_MPT_ASSERT_FAIL, MPT_NoArgValues());
MPT_Test(MPT_ASSERT_FAIL, call, .xfail=true);
/************************************************************
* Test MPT_ASSERT_EQ
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_EQ_int, MPT_Args(const char *exp, int val1, int val2))
{
assert(exp);
MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%d, %d), 1st expect: %s", val1, val2, exp);
MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%d, %d), 2nd expect: %s", val1, val2, exp);
}
MPT_TestProcess(MPT_ASSERT_EQ_int, eq, id, proc_MPT_ASSERT_EQ_int, MPT_ArgValues("PASS", 1, 1));
MPT_TestProcess(MPT_ASSERT_EQ_int, lt, id, proc_MPT_ASSERT_EQ_int, MPT_ArgValues("FAIL", 1, 2));
MPT_TestProcess(MPT_ASSERT_EQ_int, gt, id, proc_MPT_ASSERT_EQ_int, MPT_ArgValues("FAIL", 3, 2));
MPT_Test(MPT_ASSERT_EQ_int, eq, .xfail=false);
MPT_Test(MPT_ASSERT_EQ_int, lt, .xfail=true);
MPT_Test(MPT_ASSERT_EQ_int, gt, .xfail=true);
MPT_ProcessEntry(proc_MPT_ASSERT_EQ_double, MPT_Args(const char *exp, double val1, double val2))
{
assert(exp);
MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%f, %f), 1st expect: %s", val1, val2, exp);
MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%f, %f), 2nd expect: %s", val1, val2, exp);
}
MPT_TestProcess(MPT_ASSERT_EQ_double, eq, id, proc_MPT_ASSERT_EQ_double, MPT_ArgValues("PASS", 1.1, 1.1));
MPT_TestProcess(MPT_ASSERT_EQ_double, lt, id, proc_MPT_ASSERT_EQ_double, MPT_ArgValues("FAIL", 1.1, 1.2));
MPT_TestProcess(MPT_ASSERT_EQ_double, gt, id, proc_MPT_ASSERT_EQ_double, MPT_ArgValues("FAIL", 1.3, 1.2));
MPT_Test(MPT_ASSERT_EQ_double, eq, .xfail=false);
MPT_Test(MPT_ASSERT_EQ_double, lt, .xfail=true);
MPT_Test(MPT_ASSERT_EQ_double, gt, .xfail=true);
/************************************************************
* Test MPT_ASSERT_NEQ
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_NEQ_int, MPT_Args(const char *exp, int val1, int val2))
{
assert(exp);
MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%d, %d), 1st expect: %s", val1, val2, exp);
MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%d, %d), 2nd expect: %s", val1, val2, exp);
}
MPT_TestProcess(MPT_ASSERT_NEQ_int, eq, id, proc_MPT_ASSERT_NEQ_int, MPT_ArgValues("FAIL", 1, 1));
MPT_TestProcess(MPT_ASSERT_NEQ_int, lt, id, proc_MPT_ASSERT_NEQ_int, MPT_ArgValues("PASS", 1, 2));
MPT_TestProcess(MPT_ASSERT_NEQ_int, gt, id, proc_MPT_ASSERT_NEQ_int, MPT_ArgValues("PASS", 3, 2));
MPT_Test(MPT_ASSERT_NEQ_int, eq, .xfail=true);
MPT_Test(MPT_ASSERT_NEQ_int, lt, .xfail=false);
MPT_Test(MPT_ASSERT_NEQ_int, gt, .xfail=false);
MPT_ProcessEntry(proc_MPT_ASSERT_NEQ_double, MPT_Args(const char *exp, double val1, double val2))
{
assert(exp);
MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%f, %f), 1st expect: %s", val1, val2, exp);
MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%f, %f), 2nd expect: %s", val1, val2, exp);
}
MPT_TestProcess(MPT_ASSERT_NEQ_double, eq, id, proc_MPT_ASSERT_NEQ_double, MPT_ArgValues("FAIL", 1.1, 1.1));
MPT_TestProcess(MPT_ASSERT_NEQ_double, lt, id, proc_MPT_ASSERT_NEQ_double, MPT_ArgValues("PASS", 1.1, 1.2));
MPT_TestProcess(MPT_ASSERT_NEQ_double, gt, id, proc_MPT_ASSERT_NEQ_double, MPT_ArgValues("PASS", 1.3, 1.2));
MPT_Test(MPT_ASSERT_NEQ_double, eq, .xfail=true);
MPT_Test(MPT_ASSERT_NEQ_double, lt, .xfail=false);
MPT_Test(MPT_ASSERT_NEQ_double, gt, .xfail=false);
/************************************************************
* Test MPT_ASSERT_LEQ
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_LEQ_int, MPT_Args(const char *exp, int val1, int val2))
{
assert(exp);
MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%d, %d), 1st expect: %s", val1, val2, exp);
MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%d, %d), 2nd expect: %s", val1, val2, exp);
}
MPT_TestProcess(MPT_ASSERT_LEQ_int, eq, id, proc_MPT_ASSERT_LEQ_int, MPT_ArgValues("PASS", 1, 1));
MPT_TestProcess(MPT_ASSERT_LEQ_int, lt, id, proc_MPT_ASSERT_LEQ_int, MPT_ArgValues("PASS", 1, 2));
MPT_TestProcess(MPT_ASSERT_LEQ_int, gt, id, proc_MPT_ASSERT_LEQ_int, MPT_ArgValues("FAIL", 3, 2));
MPT_Test(MPT_ASSERT_LEQ_int, eq, .xfail=false);
MPT_Test(MPT_ASSERT_LEQ_int, lt, .xfail=false);
MPT_Test(MPT_ASSERT_LEQ_int, gt, .xfail=true);
MPT_ProcessEntry(proc_MPT_ASSERT_LEQ_double, MPT_Args(const char *exp, double val1, double val2))
{
assert(exp);
MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%f, %f), 1st expect: %s", val1, val2, exp);
MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%f, %f), 2nd expect: %s", val1, val2, exp);
}
MPT_TestProcess(MPT_ASSERT_LEQ_double, eq, id, proc_MPT_ASSERT_LEQ_double, MPT_ArgValues("PASS", 1.1, 1.1));
MPT_TestProcess(MPT_ASSERT_LEQ_double, lt, id, proc_MPT_ASSERT_LEQ_double, MPT_ArgValues("PASS", 1.1, 1.2));
MPT_TestProcess(MPT_ASSERT_LEQ_double, gt, id, proc_MPT_ASSERT_LEQ_double, MPT_ArgValues("FAIL", 1.3, 1.2));
MPT_Test(MPT_ASSERT_LEQ_double, eq, .xfail=false);
MPT_Test(MPT_ASSERT_LEQ_double, lt, .xfail=false);
MPT_Test(MPT_ASSERT_LEQ_double, gt, .xfail=true);
/************************************************************
* Test MPT_ASSERT_GEQ
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_GEQ_int, MPT_Args(const char *exp, int val1, int val2))
{
assert(exp);
MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%d, %d), 1st expect: %s", val1, val2, exp);
MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%d, %d), 2nd expect: %s", val1, val2, exp);
}
MPT_TestProcess(MPT_ASSERT_GEQ_int, eq, id, proc_MPT_ASSERT_GEQ_int, MPT_ArgValues("PASS", 1, 1));
MPT_TestProcess(MPT_ASSERT_GEQ_int, lt, id, proc_MPT_ASSERT_GEQ_int, MPT_ArgValues("FAIL", 1, 2));
MPT_TestProcess(MPT_ASSERT_GEQ_int, gt, id, proc_MPT_ASSERT_GEQ_int, MPT_ArgValues("PASS", 3, 2));
MPT_Test(MPT_ASSERT_GEQ_int, eq, .xfail=false);
MPT_Test(MPT_ASSERT_GEQ_int, lt, .xfail=true);
MPT_Test(MPT_ASSERT_GEQ_int, gt, .xfail=false);
MPT_ProcessEntry(proc_MPT_ASSERT_GEQ_double, MPT_Args(const char *exp, double val1, double val2))
{
assert(exp);
MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%f, %f), 1st expect: %s", val1, val2, exp);
MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%f, %f), 2nd expect: %s", val1, val2, exp);
}
MPT_TestProcess(MPT_ASSERT_GEQ_double, eq, id, proc_MPT_ASSERT_GEQ_double, MPT_ArgValues("PASS", 1.1, 1.1));
MPT_TestProcess(MPT_ASSERT_GEQ_double, lt, id, proc_MPT_ASSERT_GEQ_double, MPT_ArgValues("FAIL", 1.1, 1.2));
MPT_TestProcess(MPT_ASSERT_GEQ_double, gt, id, proc_MPT_ASSERT_GEQ_double, MPT_ArgValues("PASS", 1.3, 1.2));
MPT_Test(MPT_ASSERT_GEQ_double, eq, .xfail=false);
MPT_Test(MPT_ASSERT_GEQ_double, lt, .xfail=true);
MPT_Test(MPT_ASSERT_GEQ_double, gt, .xfail=false);
/************************************************************
* Test MPT_ASSERT_LT
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_LT_int, MPT_Args(const char *exp, int val1, int val2))
{
assert(exp);
MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%d, %d), 1st expect: %s", val1, val2, exp);
MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%d, %d), 2nd expect: %s", val1, val2, exp);
}
MPT_TestProcess(MPT_ASSERT_LT_int, eq, id, proc_MPT_ASSERT_LT_int, MPT_ArgValues("FAIL", 1, 1));
MPT_TestProcess(MPT_ASSERT_LT_int, lt, id, proc_MPT_ASSERT_LT_int, MPT_ArgValues("PASS", 1, 2));
MPT_TestProcess(MPT_ASSERT_LT_int, gt, id, proc_MPT_ASSERT_LT_int, MPT_ArgValues("FAIL", 3, 2));
MPT_Test(MPT_ASSERT_LT_int, eq, .xfail=true);
MPT_Test(MPT_ASSERT_LT_int, lt, .xfail=false);
MPT_Test(MPT_ASSERT_LT_int, gt, .xfail=true);
MPT_ProcessEntry(proc_MPT_ASSERT_LT_double, MPT_Args(const char *exp, double val1, double val2))
{
assert(exp);
MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%f, %f), 1st expect: %s", val1, val2, exp);
MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%f, %f), 2nd expect: %s", val1, val2, exp);
}
MPT_TestProcess(MPT_ASSERT_LT_double, eq, id, proc_MPT_ASSERT_LT_double, MPT_ArgValues("FAIL", 1.1, 1.1));
MPT_TestProcess(MPT_ASSERT_LT_double, lt, id, proc_MPT_ASSERT_LT_double, MPT_ArgValues("PASS", 1.1, 1.2));
MPT_TestProcess(MPT_ASSERT_LT_double, gt, id, proc_MPT_ASSERT_LT_double, MPT_ArgValues("FAIL", 1.3, 1.2));
MPT_Test(MPT_ASSERT_LT_double, eq, .xfail=true);
MPT_Test(MPT_ASSERT_LT_double, lt, .xfail=false);
MPT_Test(MPT_ASSERT_LT_double, gt, .xfail=true);
/************************************************************
* Test MPT_ASSERT_GT
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_GT_int, MPT_Args(const char *exp, int val1, int val2))
{
assert(exp);
MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%d, %d), 1st expect: %s", val1, val2, exp);
MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%d, %d), 2nd expect: %s", val1, val2, exp);
}
MPT_TestProcess(MPT_ASSERT_GT_int, eq, id, proc_MPT_ASSERT_GT_int, MPT_ArgValues("FAIL", 1, 1));
MPT_TestProcess(MPT_ASSERT_GT_int, lt, id, proc_MPT_ASSERT_GT_int, MPT_ArgValues("FAIL", 1, 2));
MPT_TestProcess(MPT_ASSERT_GT_int, gt, id, proc_MPT_ASSERT_GT_int, MPT_ArgValues("PASS", 3, 2));
MPT_Test(MPT_ASSERT_GT_int, eq, .xfail=true);
MPT_Test(MPT_ASSERT_GT_int, lt, .xfail=true);
MPT_Test(MPT_ASSERT_GT_int, gt, .xfail=false);
MPT_ProcessEntry(proc_MPT_ASSERT_GT_double, MPT_Args(const char *exp, double val1, double val2))
{
assert(exp);
MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%f, %f), 1st expect: %s", val1, val2, exp);
MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%f, %f), 2nd expect: %s", val1, val2, exp);
}
MPT_TestProcess(MPT_ASSERT_GT_double, eq, id, proc_MPT_ASSERT_GT_double, MPT_ArgValues("FAIL", 1.1, 1.1));
MPT_TestProcess(MPT_ASSERT_GT_double, lt, id, proc_MPT_ASSERT_GT_double, MPT_ArgValues("FAIL", 1.1, 1.2));
MPT_TestProcess(MPT_ASSERT_GT_double, gt, id, proc_MPT_ASSERT_GT_double, MPT_ArgValues("PASS", 1.3, 1.2));
MPT_Test(MPT_ASSERT_GT_double, eq, .xfail=true);
MPT_Test(MPT_ASSERT_GT_double, lt, .xfail=true);
MPT_Test(MPT_ASSERT_GT_double, gt, .xfail=false);
/************************************************************
* Test MPT_ASSERT_NULL
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_NULL, MPT_Args(const char *exp, const void* ptr))
{
assert(exp);
MPT_ASSERT_NULL(ptr, "MPT_ASSERT_NULL(%p), expect: %s", ptr, exp);
}
MPT_TestProcess(MPT_ASSERT_NULL, addr, id, proc_MPT_ASSERT_NULL, MPT_ArgValues("FAIL", &dummy));
MPT_TestProcess(MPT_ASSERT_NULL, null, id, proc_MPT_ASSERT_NULL, MPT_ArgValues("PASS", NULL));
MPT_Test(MPT_ASSERT_NULL, addr, .xfail=true);
MPT_Test(MPT_ASSERT_NULL, null, .xfail=false);
/************************************************************
* Test MPT_ASSERT_NOT_NULL
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_NOT_NULL, MPT_Args(const char *exp, const void* ptr))
{
assert(exp);
MPT_ASSERT_NOT_NULL(ptr, "MPT_ASSERT_NOT_NULL(%p), expect: %s", ptr, exp);
}
MPT_TestProcess(MPT_ASSERT_NOT_NULL, addr, id, proc_MPT_ASSERT_NOT_NULL, MPT_ArgValues("PASS", &dummy));
MPT_TestProcess(MPT_ASSERT_NOT_NULL, null, id, proc_MPT_ASSERT_NOT_NULL, MPT_ArgValues("FAIL", NULL));
MPT_Test(MPT_ASSERT_NOT_NULL, addr, .xfail=false);
MPT_Test(MPT_ASSERT_NOT_NULL, null, .xfail=true);
/************************************************************
* Test MPT_ASSERT_STR_EQ
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_STR_EQ, MPT_Args(const char *exp, const char* val1, const char* val2))
{
assert(exp);
MPT_ASSERT_STR_EQ(val1, val2, "MPT_ASSERT_STR_EQ(%s, %s), expect: %s",
val1 ? val1 : "<null>",
val2 ? val2 : "<null>",
exp);
}
MPT_TestProcess(MPT_ASSERT_STR_EQ, eq, id, proc_MPT_ASSERT_STR_EQ, MPT_ArgValues("PASS", "foo", "foo"));
MPT_TestProcess(MPT_ASSERT_STR_EQ, neq, id, proc_MPT_ASSERT_STR_EQ, MPT_ArgValues("FAIL", "foo", "bar"));
MPT_TestProcess(MPT_ASSERT_STR_EQ, null1, id, proc_MPT_ASSERT_STR_EQ, MPT_ArgValues("FAIL", NULL, "foo"));
MPT_TestProcess(MPT_ASSERT_STR_EQ, null2, id, proc_MPT_ASSERT_STR_EQ, MPT_ArgValues("FAIL", "foo", NULL));
MPT_Test(MPT_ASSERT_STR_EQ, eq, .xfail=false);
MPT_Test(MPT_ASSERT_STR_EQ, neq, .xfail=true);
MPT_Test(MPT_ASSERT_STR_EQ, null1, .xfail=true);
MPT_Test(MPT_ASSERT_STR_EQ, null2, .xfail=true);
/************************************************************
* Test MPT_ASSERT_STR_NEQ
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_STR_NEQ, MPT_Args(const char *exp, const char* val1, const char* val2))
{
assert(exp);
MPT_ASSERT_STR_NEQ(val1, val2, "MPT_ASSERT_STR_NEQ(%s, %s), expect: %s",
val1 ? val1 : "<null>",
val2 ? val2 : "<null>",
exp);
}
MPT_TestProcess(MPT_ASSERT_STR_NEQ, eq, id, proc_MPT_ASSERT_STR_NEQ, MPT_ArgValues("FAIL", "foo", "foo"));
MPT_TestProcess(MPT_ASSERT_STR_NEQ, neq, id, proc_MPT_ASSERT_STR_NEQ, MPT_ArgValues("PASS", "foo", "bar"));
MPT_TestProcess(MPT_ASSERT_STR_NEQ, null1, id, proc_MPT_ASSERT_STR_NEQ, MPT_ArgValues("FAIL", NULL, "foo"));
MPT_TestProcess(MPT_ASSERT_STR_NEQ, null2, id, proc_MPT_ASSERT_STR_NEQ, MPT_ArgValues("FAIL", "foo", NULL));
MPT_Test(MPT_ASSERT_STR_NEQ, eq, .xfail=true);
MPT_Test(MPT_ASSERT_STR_NEQ, neq, .xfail=false);
MPT_Test(MPT_ASSERT_STR_NEQ, null1, .xfail=true);
MPT_Test(MPT_ASSERT_STR_NEQ, null2, .xfail=true);
/************************************************************
* Test MPT_ASSERT_STR_EMPTY
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_STR_EMPTY, MPT_Args(const char *exp, const char* val))
{
assert(exp);
MPT_ASSERT_STR_EMPTY(val, "MPT_ASSERT_STR_EMPTY(%s), expect: %s",
val ? val : "<null>",
exp);
}
MPT_TestProcess(MPT_ASSERT_STR_EMPTY, nempty, id, proc_MPT_ASSERT_STR_EMPTY, MPT_ArgValues("FAIL", "foo"));
MPT_TestProcess(MPT_ASSERT_STR_EMPTY, empty, id, proc_MPT_ASSERT_STR_EMPTY, MPT_ArgValues("PASS", ""));
MPT_TestProcess(MPT_ASSERT_STR_EMPTY, null, id, proc_MPT_ASSERT_STR_EMPTY, MPT_ArgValues("FAIL", NULL));
MPT_Test(MPT_ASSERT_STR_EMPTY, nempty, .xfail=true);
MPT_Test(MPT_ASSERT_STR_EMPTY, empty, .xfail=false);
MPT_Test(MPT_ASSERT_STR_EMPTY, null, .xfail=true);
/************************************************************
* Test MPT_ASSERT_STR_NOT_EMPTY
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_STR_NOT_EMPTY, MPT_Args(const char *exp, const char* val))
{
assert(exp);
MPT_ASSERT_STR_NOT_EMPTY(val, "MPT_ASSERT_STR_NOT_EMPTY(%s), expect: %s",
val ? val : "<null>",
exp);
}
MPT_TestProcess(MPT_ASSERT_STR_NOT_EMPTY, nempty, id, proc_MPT_ASSERT_STR_NOT_EMPTY, MPT_ArgValues("PASS", "foo"));
MPT_TestProcess(MPT_ASSERT_STR_NOT_EMPTY, empty, id, proc_MPT_ASSERT_STR_NOT_EMPTY, MPT_ArgValues("FAIL", ""));
MPT_TestProcess(MPT_ASSERT_STR_NOT_EMPTY, null, id, proc_MPT_ASSERT_STR_NOT_EMPTY, MPT_ArgValues("FAIL", NULL));
MPT_Test(MPT_ASSERT_STR_NOT_EMPTY, nempty, .xfail=false);
MPT_Test(MPT_ASSERT_STR_NOT_EMPTY, empty, .xfail=true);
MPT_Test(MPT_ASSERT_STR_NOT_EMPTY, null, .xfail=true);
/*****************************************************************************/
/************************************************************
* Test MPT_ASSERT_FATAL
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL, MPT_Args(const char *exp, int cond))
{
assert(exp);
MPT_ASSERT_FATAL(cond, "MPT_ASSERT_FATAL(%d), expect: %s", cond, exp);
MPT_ASSERT(cond, "MPT_ASSERT(%d) after a fatal", cond);
}
MPT_TestProcess(MPT_ASSERT_FATAL, pass, id, proc_MPT_ASSERT_FATAL, MPT_ArgValues("PASS", 1));
MPT_Test(MPT_ASSERT_FATAL, pass, .xfail=false);
MPT_TestProcess(MPT_ASSERT_FATAL, fail, id, proc_MPT_ASSERT_FATAL, MPT_ArgValues("FAIL", 0));
MPT_Test(MPT_ASSERT_FATAL, fail, .xfail=true);
/************************************************************
* Test MPT_ASSERT_FATAL_FAIL
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_FAIL, MPT_NoArgs())
{
MPT_ASSERT_FATAL_FAIL("MPT_ASSERT_FATAL_FAIL(), expect a fail, always");
MPT_ASSERT_FAIL("MPT_ASSERT_FAIL() after a fatal");
}
MPT_TestProcess(MPT_ASSERT_FATAL_FAIL, fail, id, proc_MPT_ASSERT_FATAL_FAIL, MPT_NoArgValues());
MPT_Test(MPT_ASSERT_FATAL_FAIL, fail, .xfail=true);
/************************************************************
* Test MPT_ASSERT_FATAL_EQ
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_EQ_int, MPT_Args(const char *exp, int val1, int val2))
{
assert(exp);
MPT_ASSERT_FATAL_EQ(val1, val2, "MPT_ASSERT_FATAL_EQ(%d, %d), expect: %s", val1, val2, exp);
MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%d, %d) after a fatal", val1, val2);
}
MPT_TestProcess(MPT_ASSERT_FATAL_EQ_int, eq, id, proc_MPT_ASSERT_FATAL_EQ_int, MPT_ArgValues("PASS", 1, 1));
MPT_TestProcess(MPT_ASSERT_FATAL_EQ_int, lt, id, proc_MPT_ASSERT_FATAL_EQ_int, MPT_ArgValues("FAIL", 1, 2));
MPT_TestProcess(MPT_ASSERT_FATAL_EQ_int, gt, id, proc_MPT_ASSERT_FATAL_EQ_int, MPT_ArgValues("FAIL", 3, 2));
MPT_Test(MPT_ASSERT_FATAL_EQ_int, eq, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_EQ_int, lt, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_EQ_int, gt, .xfail=true);
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_EQ_double, MPT_Args(const char *exp, double val1, double val2))
{
assert(exp);
MPT_ASSERT_FATAL_EQ(val1, val2, "MPT_ASSERT_FATAL_EQ(%f, %f), expect: %s", val1, val2, exp);
MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%f, %f) after a fatal", val1, val2);
}
MPT_TestProcess(MPT_ASSERT_FATAL_EQ_double, eq, id, proc_MPT_ASSERT_FATAL_EQ_double, MPT_ArgValues("PASS", 1.1, 1.1));
MPT_TestProcess(MPT_ASSERT_FATAL_EQ_double, lt, id, proc_MPT_ASSERT_FATAL_EQ_double, MPT_ArgValues("FAIL", 1.1, 1.2));
MPT_TestProcess(MPT_ASSERT_FATAL_EQ_double, gt, id, proc_MPT_ASSERT_FATAL_EQ_double, MPT_ArgValues("FAIL", 1.3, 1.2));
MPT_Test(MPT_ASSERT_FATAL_EQ_double, eq, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_EQ_double, lt, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_EQ_double, gt, .xfail=true);
/************************************************************
* Test MPT_ASSERT_FATAL_NEQ
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_NEQ_int, MPT_Args(const char *exp, int val1, int val2))
{
assert(exp);
MPT_ASSERT_FATAL_NEQ(val1, val2, "MPT_ASSERT_FATAL_NEQ(%d, %d), expect: %s", val1, val2, exp);
MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%d, %d) after a fatal", val1, val2);
}
MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_int, eq, id, proc_MPT_ASSERT_FATAL_NEQ_int, MPT_ArgValues("FAIL", 1, 1));
MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_int, lt, id, proc_MPT_ASSERT_FATAL_NEQ_int, MPT_ArgValues("PASS", 1, 2));
MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_int, gt, id, proc_MPT_ASSERT_FATAL_NEQ_int, MPT_ArgValues("PASS", 3, 2));
MPT_Test(MPT_ASSERT_FATAL_NEQ_int, eq, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_NEQ_int, lt, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_NEQ_int, gt, .xfail=false);
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_NEQ_double, MPT_Args(const char *exp, double val1, double val2))
{
assert(exp);
MPT_ASSERT_FATAL_NEQ(val1, val2, "MPT_ASSERT_FATAL_NEQ(%f, %f), expect: %s", val1, val2, exp);
MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%f, %f) after a fatal", val1, val2);
}
MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_double, eq, id, proc_MPT_ASSERT_FATAL_NEQ_double, MPT_ArgValues("FAIL", 1.1, 1.1));
MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_double, lt, id, proc_MPT_ASSERT_FATAL_NEQ_double, MPT_ArgValues("PASS", 1.1, 1.2));
MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_double, gt, id, proc_MPT_ASSERT_FATAL_NEQ_double, MPT_ArgValues("PASS", 1.3, 1.2));
MPT_Test(MPT_ASSERT_FATAL_NEQ_double, eq, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_NEQ_double, lt, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_NEQ_double, gt, .xfail=false);
/************************************************************
* Test MPT_ASSERT_FATAL_LEQ
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_LEQ_int, MPT_Args(const char *exp, int val1, int val2))
{
assert(exp);
MPT_ASSERT_FATAL_LEQ(val1, val2, "MPT_ASSERT_FATAL_LEQ(%d, %d), expect: %s", val1, val2, exp);
MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%d, %d) after a fatal", val1, val2);
}
MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_int, eq, id, proc_MPT_ASSERT_FATAL_LEQ_int, MPT_ArgValues("PASS", 1, 1));
MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_int, lt, id, proc_MPT_ASSERT_FATAL_LEQ_int, MPT_ArgValues("PASS", 1, 2));
MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_int, gt, id, proc_MPT_ASSERT_FATAL_LEQ_int, MPT_ArgValues("FAIL", 3, 2));
MPT_Test(MPT_ASSERT_FATAL_LEQ_int, eq, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_LEQ_int, lt, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_LEQ_int, gt, .xfail=true);
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_LEQ_double, MPT_Args(const char *exp, double val1, double val2))
{
assert(exp);
MPT_ASSERT_FATAL_LEQ(val1, val2, "MPT_ASSERT_FATAL_LEQ(%f, %f), expect: %s", val1, val2, exp);
MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%f, %f) after a fatal", val1, val2);
}
MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_double, eq, id, proc_MPT_ASSERT_FATAL_LEQ_double, MPT_ArgValues("PASS", 1.1, 1.1));
MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_double, lt, id, proc_MPT_ASSERT_FATAL_LEQ_double, MPT_ArgValues("PASS", 1.1, 1.2));
MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_double, gt, id, proc_MPT_ASSERT_FATAL_LEQ_double, MPT_ArgValues("FAIL", 1.3, 1.2));
MPT_Test(MPT_ASSERT_FATAL_LEQ_double, eq, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_LEQ_double, lt, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_LEQ_double, gt, .xfail=true);
/************************************************************
* Test MPT_ASSERT_FATAL_GEQ
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_GEQ_int, MPT_Args(const char *exp, int val1, int val2))
{
assert(exp);
MPT_ASSERT_FATAL_GEQ(val1, val2, "MPT_ASSERT_FATAL_GEQ(%d, %d), expect: %s", val1, val2, exp);
MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%d, %d) after a fatal", val1, val2);
}
MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_int, eq, id, proc_MPT_ASSERT_FATAL_GEQ_int, MPT_ArgValues("PASS", 1, 1));
MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_int, lt, id, proc_MPT_ASSERT_FATAL_GEQ_int, MPT_ArgValues("FAIL", 1, 2));
MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_int, gt, id, proc_MPT_ASSERT_FATAL_GEQ_int, MPT_ArgValues("PASS", 3, 2));
MPT_Test(MPT_ASSERT_FATAL_GEQ_int, eq, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_GEQ_int, lt, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_GEQ_int, gt, .xfail=false);
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_GEQ_double, MPT_Args(const char *exp, double val1, double val2))
{
assert(exp);
MPT_ASSERT_FATAL_GEQ(val1, val2, "MPT_ASSERT_FATAL_GEQ(%f, %f), expect: %s", val1, val2, exp);
MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%f, %f) after a fatal", val1, val2);
}
MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_double, eq, id, proc_MPT_ASSERT_FATAL_GEQ_double, MPT_ArgValues("PASS", 1.1, 1.1));
MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_double, lt, id, proc_MPT_ASSERT_FATAL_GEQ_double, MPT_ArgValues("FAIL", 1.1, 1.2));
MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_double, gt, id, proc_MPT_ASSERT_FATAL_GEQ_double, MPT_ArgValues("PASS", 1.3, 1.2));
MPT_Test(MPT_ASSERT_FATAL_GEQ_double, eq, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_GEQ_double, lt, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_GEQ_double, gt, .xfail=false);
/************************************************************
* Test MPT_ASSERT_FATAL_LT
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_LT_int, MPT_Args(const char *exp, int val1, int val2))
{
assert(exp);
MPT_ASSERT_FATAL_LT(val1, val2, "MPT_ASSERT_FATAL_LT(%d, %d), expect: %s", val1, val2, exp);
MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%d, %d) after a fatal", val1, val2);
}
MPT_TestProcess(MPT_ASSERT_FATAL_LT_int, eq, id, proc_MPT_ASSERT_FATAL_LT_int, MPT_ArgValues("FAIL", 1, 1));
MPT_TestProcess(MPT_ASSERT_FATAL_LT_int, lt, id, proc_MPT_ASSERT_FATAL_LT_int, MPT_ArgValues("PASS", 1, 2));
MPT_TestProcess(MPT_ASSERT_FATAL_LT_int, gt, id, proc_MPT_ASSERT_FATAL_LT_int, MPT_ArgValues("FAIL", 3, 2));
MPT_Test(MPT_ASSERT_FATAL_LT_int, eq, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_LT_int, lt, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_LT_int, gt, .xfail=true);
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_LT_double, MPT_Args(const char *exp, double val1, double val2))
{
assert(exp);
MPT_ASSERT_FATAL_LT(val1, val2, "MPT_ASSERT_FATAL_LT(%f, %f), expect: %s", val1, val2, exp);
MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%f, %f) after a fatal", val1, val2);
}
MPT_TestProcess(MPT_ASSERT_FATAL_LT_double, eq, id, proc_MPT_ASSERT_FATAL_LT_double, MPT_ArgValues("FAIL", 1.1, 1.1));
MPT_TestProcess(MPT_ASSERT_FATAL_LT_double, lt, id, proc_MPT_ASSERT_FATAL_LT_double, MPT_ArgValues("PASS", 1.1, 1.2));
MPT_TestProcess(MPT_ASSERT_FATAL_LT_double, gt, id, proc_MPT_ASSERT_FATAL_LT_double, MPT_ArgValues("FAIL", 1.3, 1.2));
MPT_Test(MPT_ASSERT_FATAL_LT_double, eq, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_LT_double, lt, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_LT_double, gt, .xfail=true);
/************************************************************
* Test MPT_ASSERT_FATAL_GT
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_GT_int, MPT_Args(const char *exp, int val1, int val2))
{
assert(exp);
MPT_ASSERT_FATAL_GT(val1, val2, "MPT_ASSERT_FATAL_GT(%d, %d), expect: %s", val1, val2, exp);
MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%d, %d) after a fatal", val1, val2);
}
MPT_TestProcess(MPT_ASSERT_FATAL_GT_int, eq, id, proc_MPT_ASSERT_FATAL_GT_int, MPT_ArgValues("FAIL", 1, 1));
MPT_TestProcess(MPT_ASSERT_FATAL_GT_int, lt, id, proc_MPT_ASSERT_FATAL_GT_int, MPT_ArgValues("FAIL", 1, 2));
MPT_TestProcess(MPT_ASSERT_FATAL_GT_int, gt, id, proc_MPT_ASSERT_FATAL_GT_int, MPT_ArgValues("PASS", 3, 2));
MPT_Test(MPT_ASSERT_FATAL_GT_int, eq, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_GT_int, lt, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_GT_int, gt, .xfail=false);
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_GT_double, MPT_Args(const char *exp, double val1, double val2))
{
assert(exp);
MPT_ASSERT_FATAL_GT(val1, val2, "MPT_ASSERT_FATAL_GT(%f, %f), expect: %s", val1, val2, exp);
MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%f, %f) after a fatal", val1, val2);
}
MPT_TestProcess(MPT_ASSERT_FATAL_GT_double, eq, id, proc_MPT_ASSERT_FATAL_GT_double, MPT_ArgValues("FAIL", 1.1, 1.1));
MPT_TestProcess(MPT_ASSERT_FATAL_GT_double, lt, id, proc_MPT_ASSERT_FATAL_GT_double, MPT_ArgValues("FAIL", 1.1, 1.2));
MPT_TestProcess(MPT_ASSERT_FATAL_GT_double, gt, id, proc_MPT_ASSERT_FATAL_GT_double, MPT_ArgValues("PASS", 1.3, 1.2));
MPT_Test(MPT_ASSERT_FATAL_GT_double, eq, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_GT_double, lt, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_GT_double, gt, .xfail=false);
/************************************************************
* Test MPT_ASSERT_FATAL_NULL
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_NULL, MPT_Args(const char *exp, const void* ptr))
{
assert(exp);
MPT_ASSERT_FATAL_NULL(ptr, "MPT_ASSERT_FATAL_NULL(%p), expect: %s", ptr, exp);
}
MPT_TestProcess(MPT_ASSERT_FATAL_NULL, addr, id, proc_MPT_ASSERT_FATAL_NULL, MPT_ArgValues("FAIL", &dummy));
MPT_TestProcess(MPT_ASSERT_FATAL_NULL, null, id, proc_MPT_ASSERT_FATAL_NULL, MPT_ArgValues("PASS", NULL));
MPT_Test(MPT_ASSERT_FATAL_NULL, addr, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_NULL, null, .xfail=false);
/************************************************************
* Test MPT_ASSERT_FATAL_NOT_NULL
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_NOT_NULL, MPT_Args(const char *exp, const void* ptr))
{
assert(exp);
MPT_ASSERT_FATAL_NOT_NULL(ptr, "MPT_ASSERT_FATAL_NOT_NULL(%p), expect: %s", ptr, exp);
}
MPT_TestProcess(MPT_ASSERT_FATAL_NOT_NULL, addr, id, proc_MPT_ASSERT_FATAL_NOT_NULL, MPT_ArgValues("PASS", &dummy));
MPT_TestProcess(MPT_ASSERT_FATAL_NOT_NULL, null, id, proc_MPT_ASSERT_FATAL_NOT_NULL, MPT_ArgValues("FAIL", NULL));
MPT_Test(MPT_ASSERT_FATAL_NOT_NULL, addr, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_NOT_NULL, null, .xfail=true);
/************************************************************
* Test MPT_ASSERT_FATAL_STR_EQ
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_STR_EQ, MPT_Args(const char *exp, const char* val1, const char* val2))
{
assert(exp);
MPT_ASSERT_FATAL_STR_EQ(val1, val2, "MPT_ASSERT_FATAL_STR_EQ(%s, %s), expect: %s",
val1 ? val1 : "<null>",
val2 ? val2 : "<null>",
exp);
}
MPT_TestProcess(MPT_ASSERT_FATAL_STR_EQ, eq, id, proc_MPT_ASSERT_FATAL_STR_EQ, MPT_ArgValues("PASS", "foo", "foo"));
MPT_TestProcess(MPT_ASSERT_FATAL_STR_EQ, neq, id, proc_MPT_ASSERT_FATAL_STR_EQ, MPT_ArgValues("FAIL", "foo", "bar"));
MPT_TestProcess(MPT_ASSERT_FATAL_STR_EQ, null1, id, proc_MPT_ASSERT_FATAL_STR_EQ, MPT_ArgValues("FAIL", NULL, "foo"));
MPT_TestProcess(MPT_ASSERT_FATAL_STR_EQ, null2, id, proc_MPT_ASSERT_FATAL_STR_EQ, MPT_ArgValues("FAIL", "foo", NULL));
MPT_Test(MPT_ASSERT_FATAL_STR_EQ, eq, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_STR_EQ, neq, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_STR_EQ, null1, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_STR_EQ, null2, .xfail=true);
/************************************************************
* Test MPT_ASSERT_FATAL_STR_NEQ
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_STR_NEQ, MPT_Args(const char *exp, const char* val1, const char* val2))
{
assert(exp);
MPT_ASSERT_FATAL_STR_NEQ(val1, val2, "MPT_ASSERT_FATAL_STR_NEQ(%s, %s), expect: %s",
val1 ? val1 : "<null>",
val2 ? val2 : "<null>",
exp);
}
MPT_TestProcess(MPT_ASSERT_FATAL_STR_NEQ, eq, id, proc_MPT_ASSERT_FATAL_STR_NEQ, MPT_ArgValues("FAIL", "foo", "foo"));
MPT_TestProcess(MPT_ASSERT_FATAL_STR_NEQ, neq, id, proc_MPT_ASSERT_FATAL_STR_NEQ, MPT_ArgValues("PASS", "foo", "bar"));
MPT_TestProcess(MPT_ASSERT_FATAL_STR_NEQ, null1, id, proc_MPT_ASSERT_FATAL_STR_NEQ, MPT_ArgValues("FAIL", NULL, "foo"));
MPT_TestProcess(MPT_ASSERT_FATAL_STR_NEQ, null2, id, proc_MPT_ASSERT_FATAL_STR_NEQ, MPT_ArgValues("FAIL", "foo", NULL));
MPT_Test(MPT_ASSERT_FATAL_STR_NEQ, eq, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_STR_NEQ, neq, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_STR_NEQ, null1, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_STR_NEQ, null2, .xfail=true);
/************************************************************
* Test MPT_ASSERT_FATAL_STR_EMPTY
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_STR_EMPTY, MPT_Args(const char *exp, const char* val))
{
assert(exp);
MPT_ASSERT_FATAL_STR_EMPTY(val, "MPT_ASSERT_FATAL_STR_EMPTY(%s), expect: %s",
val ? val : "<null>",
exp);
}
MPT_TestProcess(MPT_ASSERT_FATAL_STR_EMPTY, nempty, id, proc_MPT_ASSERT_FATAL_STR_EMPTY, MPT_ArgValues("FAIL", "foo"));
MPT_TestProcess(MPT_ASSERT_FATAL_STR_EMPTY, empty, id, proc_MPT_ASSERT_FATAL_STR_EMPTY, MPT_ArgValues("PASS", ""));
MPT_TestProcess(MPT_ASSERT_FATAL_STR_EMPTY, null, id, proc_MPT_ASSERT_FATAL_STR_EMPTY, MPT_ArgValues("FAIL", NULL));
MPT_Test(MPT_ASSERT_FATAL_STR_EMPTY, nempty, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_STR_EMPTY, empty, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_STR_EMPTY, null, .xfail=true);
/************************************************************
* Test MPT_ASSERT_FATAL_STR_NOT_EMPTY
************************************************************/
MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_STR_NOT_EMPTY, MPT_Args(const char *exp, const char* val))
{
assert(exp);
MPT_ASSERT_FATAL_STR_NOT_EMPTY(val, "MPT_ASSERT_FATAL_STR_NOT_EMPTY(%s), expect: %s",
val ? val : "<null>",
exp);
}
MPT_TestProcess(MPT_ASSERT_FATAL_STR_NOT_EMPTY, nempty, id, proc_MPT_ASSERT_FATAL_STR_NOT_EMPTY, MPT_ArgValues("PASS", "foo"));
MPT_TestProcess(MPT_ASSERT_FATAL_STR_NOT_EMPTY, empty, id, proc_MPT_ASSERT_FATAL_STR_NOT_EMPTY, MPT_ArgValues("FAIL", ""));
MPT_TestProcess(MPT_ASSERT_FATAL_STR_NOT_EMPTY, null, id, proc_MPT_ASSERT_FATAL_STR_NOT_EMPTY, MPT_ArgValues("FAIL", NULL));
MPT_Test(MPT_ASSERT_FATAL_STR_NOT_EMPTY, nempty, .xfail=false);
MPT_Test(MPT_ASSERT_FATAL_STR_NOT_EMPTY, empty, .xfail=true);
MPT_Test(MPT_ASSERT_FATAL_STR_NOT_EMPTY, null, .xfail=true);
/*****************************************************************************/
/************************************************************
* Test propagation,
* Check if failure/success is actually propagated to ctest.
************************************************************/
MPT_ProcessEntry(proc_propagation, MPT_Args(const char *exp, int cond, dds_duration_t delay))
{
assert(exp);
if (delay > 0) {
dds_sleepfor(delay);
}
MPT_ASSERT(cond, "MPT_ASSERT(%d), expect: %s", cond, exp);
}
/* This should pass in the ctest results. */
MPT_TestProcess(propagation, pass, id1, proc_propagation, MPT_ArgValues("PASS", 1, 0));
MPT_TestProcess(propagation, pass, id2, proc_propagation, MPT_ArgValues("PASS", 1, 0));
MPT_Test(propagation, pass);
/* This should fail in the ctest results. */
MPT_TestProcess(propagation, fail_1st, id1, proc_propagation, MPT_ArgValues("FAIL", 0, 0));
MPT_TestProcess(propagation, fail_1st, id2, proc_propagation, MPT_ArgValues("PASS", 1, DDS_SECS(1)));
MPT_Test(propagation, fail_1st);
/* This should fail in the ctest results. */
MPT_TestProcess(propagation, fail_2nd, id1, proc_propagation, MPT_ArgValues("PASS", 1, 0));
MPT_TestProcess(propagation, fail_2nd, id2, proc_propagation, MPT_ArgValues("FAIL", 0, DDS_SECS(1)));
MPT_Test(propagation, fail_2nd);

View file

@ -0,0 +1,96 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "mpt/mpt.h"
#include "mpt/resource.h" /* MPT_SOURCE_ROOT_DIR */
#include "dds/ddsrt/environ.h"
/************************************************************
* Process
************************************************************/
MPT_ProcessEntry(proc_environments, MPT_Args(mpt_env_t *exp))
{
assert(exp);
while ((exp->name != NULL) && (exp->value != NULL)) {
/* The environment variable value should match the expected value. */
char *ptr = NULL;
ddsrt_getenv(exp->name, &ptr);
if (ptr) {
MPT_ASSERT((strcmp(exp->value, ptr) == 0), "%s: found \"%s\", expected \"%s\"", exp->name, ptr, exp->value);
} else {
MPT_ASSERT(0, "Expected \"%s\" not found in environment", exp->name);
}
exp++;
}
}
/************************************************************
* Basic environment tests
************************************************************/
static mpt_env_t environ_basic[] = {
{ "MY_ENV_VAR1", "1" },
{ "MY_ENV_VAR2", "2" },
{ NULL, NULL }
};
MPT_TestProcess(environment, proc, id, proc_environments, MPT_ArgValues(environ_basic), .environment=environ_basic);
MPT_Test(environment, proc);
MPT_TestProcess(environment, test, id, proc_environments, MPT_ArgValues(environ_basic));
MPT_Test(environment, test, .environment=environ_basic);
/************************************************************
* Expanding variables environment tests
************************************************************/
static mpt_env_t environ_expand[] = {
{ "1", "b" },
{ "2", "${1}l" },
{ "3", "${2}aat" },
{ "4", "bla${1}${2}a${3}" },
{ NULL, NULL }
};
static mpt_env_t expect_expand[] = {
{ "1", "b" },
{ "2", "bl" },
{ "3", "blaat" },
{ "4", "blabblablaat" },
{ NULL, NULL }
};
MPT_TestProcess(environment, expand_proc, id, proc_environments, MPT_ArgValues(expect_expand), .environment=environ_expand);
MPT_Test(environment, expand_proc);
MPT_TestProcess(environment, expand_test, id, proc_environments, MPT_ArgValues(expect_expand));
MPT_Test(environment, expand_test, .environment=environ_expand);
/************************************************************
* Environment inheritance test
************************************************************/
static mpt_env_t environ_test[] = {
{ "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/self/etc" },
{ "OVERRULE", "NO" },
{ NULL, NULL }
};
static mpt_env_t environ_proc[] = {
{ "CYCLONE_URI", "file://${ETC_DIR}/ospl.xml" },
{ "OVERRULE", "YES" },
{ "EXTRA", "proc" },
{ NULL, NULL }
};
static mpt_env_t environ_test_proc[] = {
{ "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/self/etc" },
{ "CYCLONE_URI", "file://"MPT_SOURCE_ROOT_DIR"/tests/self/etc/ospl.xml" },
{ "OVERRULE", "YES" },
{ "EXTRA", "proc" },
{ NULL, NULL }
};
MPT_TestProcess(environment, inheritance, id, proc_environments, MPT_ArgValues(environ_test_proc), .environment=environ_proc);
MPT_Test(environment, inheritance, .environment=environ_test);

View file

View file

@ -0,0 +1,72 @@
#include <stdio.h>
#include "mpt/mpt.h"
#include "mpt/resource.h" /* MPT_SOURCE_ROOT_DIR */
#include "dds/ddsrt/time.h"
/************************************************************
* Support functions
************************************************************/
static int g_initcnt = 0;
static void init_inc(void)
{
g_initcnt++;
};
/************************************************************
* Processes
************************************************************/
MPT_ProcessEntry(proc_initcnt, MPT_Args(int init))
{
MPT_ASSERT((g_initcnt == init), "init count: %d vs %d", g_initcnt, init);
}
MPT_ProcessEntry(proc_sleep, MPT_Args(dds_duration_t delay))
{
MPT_ASSERT((delay > 0), "basically just to satisfy the compiler");
dds_sleepfor(delay);
}
/************************************************************
* Init fixture tests
************************************************************/
MPT_TestProcess(init, none, id, proc_initcnt, MPT_ArgValues(0));
MPT_Test(init, none);
MPT_TestProcess(init, null, id, proc_initcnt, MPT_ArgValues(0), .init=NULL);
MPT_Test(init, null, .init=NULL);
MPT_TestProcess(init, proc, id, proc_initcnt, MPT_ArgValues(1), .init=init_inc);
MPT_Test(init, proc);
MPT_TestProcess(init, test, id, proc_initcnt, MPT_ArgValues(1));
MPT_Test(init, test, .init=init_inc);
MPT_TestProcess(init, test_proc, id, proc_initcnt, MPT_ArgValues(2), .init=init_inc);
MPT_Test(init, test_proc, .init=init_inc);
/************************************************************
* Disable fixture tests
************************************************************/
MPT_TestProcess(disabled, _true, id, proc_initcnt, MPT_ArgValues(0));
MPT_Test(disabled, _true, .disabled=true);
MPT_TestProcess(disabled, _false, id, proc_initcnt, MPT_ArgValues(0));
MPT_Test(disabled, _false, .disabled=false);
/************************************************************
* Timeout fixture tests
************************************************************/
/* See if a child process is killed when the parent is killed.
* This can only really be done manually, unfortunately. */
MPT_TestProcess(timeout, child_culling, id, proc_sleep, MPT_ArgValues(DDS_SECS(120)));
MPT_Test(timeout, child_culling, .timeout=1);

29
src/mpt/tests/self/ipc.c Normal file
View file

@ -0,0 +1,29 @@
#include <stdio.h>
#include "mpt/mpt.h"
/************************************************************
* Processes
************************************************************/
MPT_ProcessEntry(proc_ipc_send, MPT_NoArgs())
{
/* This will fail and cause an internal MPT assert as long
* as IPC is not yet implemented. */
MPT_Send("todo: implement");
}
MPT_ProcessEntry(proc_ipc_wait, MPT_NoArgs())
{
/* This will fail and cause an internal MPT assert as long
* as IPC is not yet implemented. */
MPT_Wait("todo: implement");
}
/************************************************************
* Tests
************************************************************/
MPT_TestProcess(ipc, TODO, id1, proc_ipc_send, MPT_NoArgValues());
MPT_TestProcess(ipc, TODO, id2, proc_ipc_wait, MPT_NoArgValues());
MPT_Test(ipc, TODO);

View file

@ -0,0 +1,30 @@
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "mpt/mpt.h"
#include "mpt/resource.h" /* MPT_SOURCE_ROOT_DIR */
/************************************************************
* Processes
************************************************************/
MPT_ProcessEntry(proc_file, MPT_NoArgs())
{
const char *test_file = MPT_SOURCE_ROOT_DIR"/tests/self/etc/file";
#if _WIN32
struct _stat buffer;
int ret = _stat(test_file,&buffer);
#else
struct stat buffer;
int ret = stat(test_file,&buffer);
#endif
MPT_ASSERT((ret == 0), "%s", test_file);
}
/************************************************************
* Test if MPT_SOURCE_ROOT_DIR is a valid location.
************************************************************/
MPT_TestProcess(resources, root_dir, id, proc_file, MPT_NoArgValues());
MPT_Test(resources, root_dir);

186
src/mpt/tests/self/usage.c Normal file
View file

@ -0,0 +1,186 @@
#include <stdio.h>
#include "mpt/mpt.h"
#include "mpt/resource.h" /* MPT_SOURCE_ROOT_DIR */
/******************************************************************************
* First, we need a process entry-point that can be used in tests.
*****************************************************************************/
/* | name | arguments | */
MPT_ProcessEntry(proc_noargs, MPT_NoArgs())
{
// Do stuff
// The test processes will use asserts to indicate success/failures.
MPT_ASSERT(1, "The problem is: %s", "existential crisis");
// No need to return anything, that's handled by the assert calls.
}
/******************************************************************************
* A process entry-point can have arguments.
*****************************************************************************/
/* | name | arguments | */
MPT_ProcessEntry(proc_args, MPT_Args(int domain, const char* text))
{
int expected = 1;
MPT_ASSERT(expected == domain, "proc_args(%d, %s)", domain, text);
}
/******************************************************************************
* Process entry-points can communicate to be able to sync fi.
*****************************************************************************/
MPT_ProcessEntry(proc_recv, MPT_NoArgs())
{
/* This will wait until another process sends the same string. */
MPT_Wait("some state reached");
}
MPT_ProcessEntry(proc_send, MPT_NoArgs())
{
/* If this fails, an internal MPT_ASSERT will be triggered.
* The same is true for MPT_Wait(). */
MPT_Send("some state reached");
}
/******************************************************************************
* Test: suitename_testA
******************************************************************************
* A simple test that starts two processes. Because a test can use the same
* process entry-point to start multiple processes, each process has to have
* its own unique id within the test.
*/
/* | process identification | entry-point | arguments | */
MPT_TestProcess(suitename, testA, id1, proc_noargs, MPT_NoArgValues());
MPT_TestProcess(suitename, testA, id2, proc_noargs, MPT_NoArgValues());
MPT_Test(suitename, testA);
/******************************************************************************
* Test: suitename_testB
******************************************************************************
* Of course, different processes can be started as well.
* Argument values are provided per test process.
*/
MPT_TestProcess(suitename, testB, id1, proc_noargs, MPT_NoArgValues( ));
MPT_TestProcess(suitename, testB, id2, proc_args, MPT_ArgValues(1, "2"));
MPT_TestProcess(suitename, testB, id3, proc_args, MPT_ArgValues(1, "3"));
MPT_Test(suitename, testB);
/******************************************************************************
* Test: suitename_testC
******************************************************************************
* The processes can have different or equal 'system environments'.
*/
mpt_env_t environment_C1[] = {
{ "CYCLONEDDS_URI", "file://config1.xml" },
{ "PERMISSIONS", "file://permissions.p7s" },
{ "GOVERNANCE", "file://governance.p7s" },
{ NULL, NULL }
};
mpt_env_t environment_C2[] = {
{ "CYCLONEDDS_URI", "file://config2.xml" },
{ "PERMISSIONS", "file://permissions.p7s" },
{ "GOVERNANCE", "file://governance.p7s" },
{ NULL, NULL }
};
MPT_TestProcess(suitename, testC, id1, proc_noargs, MPT_NoArgValues(), .environment=environment_C1);
MPT_TestProcess(suitename, testC, id2, proc_noargs, MPT_NoArgValues(), .environment=environment_C1);
MPT_TestProcess(suitename, testC, id3, proc_noargs, MPT_NoArgValues(), .environment=environment_C2);
MPT_Test(suitename, testC);
/******************************************************************************
* Test: suitename_testD
******************************************************************************
* The two environments in the previous example are partly the same.
* It's possible set the environment on test level. The environment variables
* related to the test are set before the ones related to a process. This
* means that a process can overrule variables.
*
* The following test is the same as the previous one.
*/
mpt_env_t environment_D1[] = {
{ "CYCLONEDDS_URI", "file://config1.xml" },
{ "PERMISSIONS", "file://permissions.p7s" },
{ "GOVERNANCE", "file://governance.p7s" },
{ NULL, NULL }
};
mpt_env_t environment_D2[] = {
{ "CYCLONEDDS_URI", "file://config2.xml" },
{ NULL, NULL }
};
MPT_TestProcess(suitename, testD, id1, proc_noargs, MPT_NoArgValues());
MPT_TestProcess(suitename, testD, id2, proc_noargs, MPT_NoArgValues());
MPT_TestProcess(suitename, testD, id3, proc_noargs, MPT_NoArgValues(), .environment=environment_D2);
MPT_Test(suitename, testD, .environment=environment_D1);
/******************************************************************************
* Test: suitename_testE
******************************************************************************
* Environment variables will be expanded.
* Also, the MPT_SOURCE_ROOT_DIR define contains a string to that particular
* directory.
* This can be combined to easily point to files.
*/
mpt_env_t environment_E[] = {
{ "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/self/etc" },
{ "CYCLONEDDS_URI", "file://${ETC_DIR}/config.xml" },
{ NULL, NULL }
};
MPT_TestProcess(suitename, testE, id, proc_noargs, MPT_NoArgValues(), .environment=environment_E);
MPT_Test(suitename, testE);
/******************************************************************************
* Test: suitename_testF
******************************************************************************
* The processes and tests can use init/fini fixtures.
* The test init is executed before the process init.
* The process fini is executed before the test fini.
*/
void proc_setup(void) { /* do stuff */ }
void proc_teardown(void) { /* do stuff */ }
void test_setup(void) { /* do stuff */ }
void test_teardown(void) { /* do stuff */ }
MPT_TestProcess(suitename, testF, id1, proc_noargs, MPT_NoArgValues(), .init=proc_setup);
MPT_TestProcess(suitename, testF, id2, proc_noargs, MPT_NoArgValues(), .fini=proc_teardown);
MPT_TestProcess(suitename, testF, id3, proc_noargs, MPT_NoArgValues(), .init=proc_setup, .fini=proc_teardown);
MPT_Test(suitename, testF, .init=test_setup, .fini=test_teardown);
/******************************************************************************
* Test: suitename_testG
******************************************************************************
* The timeout and disable options are handled by test fixtures.
*/
MPT_TestProcess(suitename, testG, id1, proc_noargs, MPT_NoArgValues());
MPT_TestProcess(suitename, testG, id2, proc_noargs, MPT_NoArgValues());
MPT_Test(suitename, testG, .timeout=10, .disabled=true);
/******************************************************************************
* Test: suitename_testH
******************************************************************************
* See the process entries to notice the MPT Send/Wait IPC.
*/
MPT_TestProcess(suitename, testH, id1, proc_recv, MPT_NoArgValues());
MPT_TestProcess(suitename, testH, id2, proc_send, MPT_NoArgValues());
MPT_Test(suitename, testH);