Skip to content

Commit 303b97c

Browse files
Add build TSAN test macro (#12)
* Add build TSAN test macro Signed-off-by: Juan López Fernández <juanlopez@eprosima.com> * Fix TSAN data races Signed-off-by: Juan López Fernández <juanlopez@eprosima.com> * Exclude signal handling tests in TSAN workflow Signed-off-by: Juan López Fernández <juanlopez@eprosima.com> Signed-off-by: Juan López Fernández <juanlopez@eprosima.com>
1 parent 938e46f commit 303b97c

10 files changed

Lines changed: 177 additions & 1 deletion

File tree

.github/workflows/test.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
# - Debug
1717
# - build code ; run tests
1818
#
19+
# - tsan-test
20+
# - ubuntu-20.04
21+
# - Debug
22+
# - build code ; run tests
23+
#
1924
# - ubuntu-test
2025
# - [ ubuntu-20.04 | ubuntu-22.04 ]
2126
# - [ Debug | Release ]
@@ -218,6 +223,73 @@ jobs:
218223
path: log/
219224
if: always()
220225

226+
###########################################################
227+
# TSAN TEST
228+
tsan-test:
229+
runs-on: ubuntu-20.04
230+
231+
steps:
232+
- name: Sync eProsima/dev-utils repository
233+
uses: actions/checkout@v2
234+
with:
235+
path: src/dev-utils
236+
237+
- name: Install apt packages
238+
uses: ./src/dev-utils/.github/actions/install-apt-packages
239+
240+
- name: Install GTest
241+
uses: ./src/dev-utils/.github/actions/install-gtest-linux
242+
243+
- name: Install Python packages
244+
uses: ./src/dev-utils/.github/actions/install-python-packages
245+
246+
- name: Get build eProsima dependencies Job Id
247+
run: |
248+
export JOB_ID=$(curl -sL $GITHUB_API_URL/repos/$GITHUB_REPOSITORY/actions/workflows/build_dependencies.yml/runs | \
249+
jq '.workflow_runs[] | select(.status == "completed") | .id' | \
250+
head -n 1)
251+
echo "fastdds_job_id=${JOB_ID}" >> $GITHUB_ENV
252+
253+
- name: Download eProsima dependencies
254+
uses: dawidd6/action-download-artifact@v2
255+
with:
256+
workflow: build_dependencies.yml
257+
path: /home/runner/work/fastdds/install
258+
name: ubuntu-20.04_eprosima_dependencies_install
259+
run_id: ${{ env.fastdds_job_id }}
260+
261+
- name: Update colcon mixin
262+
run: |
263+
colcon mixin add default \
264+
https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml
265+
colcon mixin update default
266+
continue-on-error: true
267+
268+
- name: Build workspace
269+
run: |
270+
source /home/runner/work/fastdds/install/setup.bash
271+
colcon build \
272+
--event-handlers=console_direct+ \
273+
--metas src/dev-utils/.github/workflows/tsan_colcon.meta
274+
275+
- name: Run tests
276+
run: |
277+
source install/setup.bash && \
278+
colcon test \
279+
--packages-select cpp_utils \
280+
--event-handlers=console_direct+ \
281+
--return-code-on-test-failure \
282+
--ctest-args \
283+
--label-exclude "xfail|xtsan" \
284+
--timeout 60
285+
286+
- name: Upload Logs
287+
uses: actions/upload-artifact@v1
288+
with:
289+
name: tsan-logs
290+
path: log/
291+
if: always()
292+
221293
###########################################################
222294
# UBUNTU TEST
223295
ubuntu-test:

.github/workflows/tsan_colcon.meta

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"names":
3+
{
4+
"cmake_utils":
5+
{
6+
"cmake-args":
7+
[
8+
"-DCMAKE_BUILD_TYPE=Debug",
9+
"-DBUILD_TESTS=ON"
10+
]
11+
},
12+
"cpp_utils":
13+
{
14+
"cmake-args":
15+
[
16+
"-DCMAKE_BUILD_TYPE=Debug",
17+
"-DBUILD_TESTS=ON",
18+
"-DTSAN_BUILD=ON"
19+
]
20+
}
21+
}
22+
}

cmake_utils/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ they will be initialized to their corresponding default value.
121121
| BUILD_TOOL | ON | Build only Application packages |
122122
| BUILD_LIBRARY | ON | Build only Library packages |
123123
| CODE_COVERAGE | OFF | Activate Code Coverage flags |
124+
| TSAN_BUILD | OFF | Activate thread sanitizer flags |
124125
| ASAN_BUILD | OFF | Activate address sanitizer flags |
125126
| CMAKE_BUILD_TYPE | Release | CMake Build Type |
126127
| LOG_INFO | OFF (ON if Debug) | Activate log info verbosity level |

cmake_utils/cmake/cpp_common/configure_project_cpp.cmake

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,16 @@ macro(configure_project_cpp)
5757
activate_code_coverage()
5858
endif()
5959

60+
if (TSAN_BUILD)
61+
activate_thread_sanitizer()
62+
endif()
63+
6064
if (ASAN_BUILD)
61-
activate_address_sanitizer()
65+
if (TSAN_BUILD)
66+
message(FATAL_ERROR "Thread sanitizer activated, cannot activate address sanitizer. Aborting.")
67+
else()
68+
activate_address_sanitizer()
69+
endif()
6270
endif()
6371

6472
# Set custom C++ Flags
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
###############################################################################
16+
# Activate Thread sanitizer
17+
###############################################################################
18+
19+
# Activate Thread sanitizer setting compilation flags
20+
macro(activate_thread_sanitizer)
21+
22+
# Warning/Error messages
23+
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug"))
24+
message(WARNING "Thread sanitizer results with an optimized (non-Debug) build may be misleading")
25+
endif()
26+
27+
if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
28+
message(STATUS "Building with llvm Thread sanitizer Tools")
29+
30+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=thread")
31+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
32+
33+
elseif(CMAKE_COMPILER_IS_GNUCXX)
34+
message(STATUS "Building with Thread sanitizer Tools")
35+
36+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=thread -fno-omit-frame-pointer")
37+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread -fno-omit-frame-pointer")
38+
else()
39+
message(FATAL_ERROR "Thread sanitizer requires Clang or GCC. Aborting.")
40+
endif()
41+
42+
endmacro()

cmake_utils/cmake/project/cmake_options.cmake

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
# - BUILD_LIBRARY : ON
3434
#
3535
# - CODE_COVERAGE : OFF
36+
# - TSAN_BUILD : OFF
3637
# - ASAN_BUILD : OFF
3738
# - CMAKE_BUILD_TYPE : Release
3839
#
@@ -85,6 +86,11 @@ macro(configure_cmake_options)
8586
set(CODE_COVERAGE OFF)
8687
endif()
8788

89+
# TSAN
90+
if (NOT DEFINED TSAN_BUILD)
91+
set(TSAN_BUILD OFF)
92+
endif()
93+
8894
# ASAN
8995
if (NOT DEFINED ASAN_BUILD)
9096
set(ASAN_BUILD OFF)

cmake_utils/cmake/test/gtest.cmake

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,12 @@ macro(add_windows_xfail_label LIST_FILE)
9090
endif()
9191
endmacro()
9292

93+
macro(add_xtsan_label LIST_FILE)
94+
if(EXISTS ${LIST_FILE})
95+
file(STRINGS ${LIST_FILE} TEST_LIST)
96+
foreach(XTSAN_TEST ${TEST_LIST})
97+
set_property(TEST ${XTSAN_TEST} PROPERTY LABELS xtsan)
98+
endforeach()
99+
endif()
100+
endmacro()
101+

cpp_utils/test/unittest/event/signal/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,6 @@ add_unittest_executable(
4242
)
4343

4444
add_windows_xfail_label(${CMAKE_CURRENT_SOURCE_DIR}/WINDOWS_TEST_XFAIL.list)
45+
46+
# TSAN captures and handles raised signals, thus these tests cannot succeed
47+
add_xtsan_label(${CMAKE_CURRENT_SOURCE_DIR}/TEST_XTSAN.list)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
SignalEventHandlerTest.receive_signal_trivial
2+
SignalEventHandlerTest.receive_signal
3+
SignalEventHandlerTest.receive_n_signals
4+
SignalEventHandlerTest.erase_callback_while_other_handling

cpp_utils/test/unittest/thread_pool/slot_thread_pool_test.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ TEST(slot_thread_pool_test, pool_one_thread_one_slot)
8282
// Wait for counter value to be greater than 0 (so 1 task is being executed)
8383
waiter.wait_greater_equal_than(test::N_EXECUTIONS_IN_TEST);
8484

85+
// Join threads before destroying waiter to avoid data race
86+
thread_pool.disable();
87+
8588
ASSERT_EQ(waiter.get_value(), test::N_EXECUTIONS_IN_TEST);
8689
}
8790

@@ -122,6 +125,9 @@ TEST(slot_thread_pool_test, pool_one_thread_n_slots)
122125
// Wait for counter value to be M being M = N*(N+1)/2 that is the increase value that should be achieved
123126
waiter.wait_greater_equal_than((test::N_EXECUTIONS_IN_TEST* (test::N_EXECUTIONS_IN_TEST + 1)) / 2);
124127

128+
// Join threads before destroying waiter to avoid data race
129+
thread_pool.disable();
130+
125131
ASSERT_EQ(waiter.get_value(), (test::N_EXECUTIONS_IN_TEST* (test::N_EXECUTIONS_IN_TEST + 1)) / 2);
126132
}
127133

@@ -161,6 +167,9 @@ TEST(slot_thread_pool_test, pool_n_threads_one_slot)
161167

162168
auto time_elapsed = timer.elapsed();
163169

170+
// Join threads before destroying waiter to avoid data race
171+
thread_pool.disable();
172+
164173
// Check that the task has been executed in more than waiting time and less than waiting time + residual time
165174
// and that function has been called exactly once
166175
ASSERT_GE(time_elapsed, test::DEFAULT_TIME_TEST* test::N_EXECUTIONS_IN_TEST);

0 commit comments

Comments
 (0)