Skip to content

test: add unit tests for the cuda_blackboard package#24

Draft
manato wants to merge 28 commits into
autowarefoundation:mainfrom
manato:feat/add_test
Draft

test: add unit tests for the cuda_blackboard package#24
manato wants to merge 28 commits into
autowarefoundation:mainfrom
manato:feat/add_test

Conversation

@manato

@manato manato commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

PR Type

  • Improvement

Related Links

Description

This PR adds unit tests for the cuda_blackboard package. The tests are intended to work with the modification added in #22, though most of them could work without the modification.

Review Procedure

# build the package
colcon build --symlink-install \
  --cmake-args -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
  --packages-up-to cuda_blackboard

# run the tests
colcon test --event-handlers console_cohesion+ \
  --packages-select cuda_blackboard
The result will look like
Starting >>> cuda_blackboard
--- output: cuda_blackboard

...

1: Running main() from /opt/ros/humble/src/gtest_vendor/src/gtest_main.cc
1: [==========] Running 3 tests from 1 test suite.
1: [----------] Global test environment set-up.
1: [----------] 3 tests from CudaBlackboardTest
1: [ RUN      ] CudaBlackboardTest.QueryByInstanceIdAndProducerConsumesTickets
1: [       OK ] CudaBlackboardTest.QueryByInstanceIdAndProducerConsumesTickets (169 ms)
1: [ RUN      ] CudaBlackboardTest.DuplicateProducerReplacesPreviousData
1: [WARN 1781573370.093582848] [CudaBlackboard]: Producer CudaBlackboardTest.DuplicateProducerReplacesPreviousData already exists. Deleting. It had 2 tickets left
1: [       OK ] CudaBlackboardTest.DuplicateProducerReplacesPreviousData (0 ms)
1: [ RUN      ] CudaBlackboardTest.MissingKeysReturnNullptr
1: [       OK ] CudaBlackboardTest.MissingKeysReturnNullptr (0 ms)
1: [----------] 3 tests from CudaBlackboardTest (169 ms total)
1:
1: [----------] Global test environment tear-down
1: [==========] 3 tests from 1 test suite ran. (169 ms total)
1: [  PASSED  ] 3 tests.
1: -- run_test.py: return code 0

...

1/6 Test #1: test_cuda_blackboard .............   Passed    0.29 sec
test 2
    Start 2: test_cuda_image

...

2: Running main() from /opt/ros/humble/src/gtest_vendor/src/gtest_main.cc
2: [==========] Running 5 tests from 1 test suite.
2: [----------] Global test environment set-up.
2: [----------] 5 tests from CudaImageTest
2: [ RUN      ] CudaImageTest.ConstructsFromRosImageAndConvertsBack
2: [       OK ] CudaImageTest.ConstructsFromRosImageAndConvertsBack (127 ms)
2: [ RUN      ] CudaImageTest.CopyConstructorDeepCopiesDeviceData
2: [WARN 1781573370.343438378] [CudaImage]: CudaImage copy constructor called. This should be avoided and is most likely a design error.
2: [       OK ] CudaImageTest.CopyConstructorDeepCopiesDeviceData (0 ms)
2: [ RUN      ] CudaImageTest.TypeAdapterRoundTripPreservesData
2: [       OK ] CudaImageTest.TypeAdapterRoundTripPreservesData (0 ms)
2: [ RUN      ] CudaImageTest.MoveConstructorTransfersDeviceData
2: [       OK ] CudaImageTest.MoveConstructorTransfersDeviceData (0 ms)
2: [ RUN      ] CudaImageTest.MoveAssignmentTransfersDeviceData
2: [       OK ] CudaImageTest.MoveAssignmentTransfersDeviceData (0 ms)
2: [----------] 5 tests from CudaImageTest (127 ms total)
2:
2: [----------] Global test environment tear-down
2: [==========] 5 tests from 1 test suite ran. (127 ms total)
2: [  PASSED  ] 5 tests.
2: -- run_test.py: return code 0

...

2/6 Test #2: test_cuda_image ..................   Passed    0.25 sec
test 3
    Start 3: test_cuda_pointcloud2

...

3: Running main() from /opt/ros/humble/src/gtest_vendor/src/gtest_main.cc
3: [==========] Running 5 tests from 1 test suite.
3: [----------] Global test environment set-up.
3: [----------] 5 tests from CudaPointCloud2Test
3: [ RUN      ] CudaPointCloud2Test.ConstructsFromRosPointCloudAndConvertsBack
3: [       OK ] CudaPointCloud2Test.ConstructsFromRosPointCloudAndConvertsBack (146 ms)
3: [ RUN      ] CudaPointCloud2Test.CopyConstructorDeepCopiesDeviceData
3: [WARN 1781573370.608095259] [CudaPointCloud2]: CudaPointCloud2 copy constructor called. This should be avoided and is most likely a design error.
3: [       OK ] CudaPointCloud2Test.CopyConstructorDeepCopiesDeviceData (0 ms)
3: [ RUN      ] CudaPointCloud2Test.TypeAdapterRoundTripPreservesData
3: [       OK ] CudaPointCloud2Test.TypeAdapterRoundTripPreservesData (0 ms)
3: [ RUN      ] CudaPointCloud2Test.MoveConstructorTransfersOwnership
3: [       OK ] CudaPointCloud2Test.MoveConstructorTransfersOwnership (0 ms)
3: [ RUN      ] CudaPointCloud2Test.MoveAssignmentTransfersOwnership
3: [       OK ] CudaPointCloud2Test.MoveAssignmentTransfersOwnership (0 ms)
3: [----------] 5 tests from CudaPointCloud2Test (146 ms total)
3:
3: [----------] Global test environment tear-down
3: [==========] 5 tests from 1 test suite ran. (146 ms total)
3: [  PASSED  ] 5 tests.
3: -- run_test.py: return code 0

...

3/6 Test #3: test_cuda_pointcloud2 ............   Passed    0.26 sec
test 4
    Start 4: test_cuda_unique_ptr

...

4: Running main() from /opt/ros/humble/src/gtest_vendor/src/gtest_main.cc
4: [==========] Running 4 tests from 2 test suites.
4: [----------] Global test environment set-up.
4: [----------] 2 tests from CudaUniquePtrTest
4: [ RUN      ] CudaUniquePtrTest.AllocatesDeviceObject
4: [       OK ] CudaUniquePtrTest.AllocatesDeviceObject (132 ms)
4: [ RUN      ] CudaUniquePtrTest.AllocatesDeviceArray
4: [       OK ] CudaUniquePtrTest.AllocatesDeviceArray (0 ms)
4: [----------] 2 tests from CudaUniquePtrTest (132 ms total)
4:
4: [----------] 2 tests from HostUniquePtrTest
4: [ RUN      ] HostUniquePtrTest.AllocatesPinnedHostObject
4: [       OK ] HostUniquePtrTest.AllocatesPinnedHostObject (1 ms)
4: [ RUN      ] HostUniquePtrTest.AllocatesPinnedHostArray
4: [       OK ] HostUniquePtrTest.AllocatesPinnedHostArray (0 ms)
4: [----------] 2 tests from HostUniquePtrTest (1 ms total)
4:
4: [----------] Global test environment tear-down
4: [==========] 4 tests from 2 test suites ran. (133 ms total)
4: [  PASSED  ] 4 tests.
4: -- run_test.py: return code 0

...

4/6 Test #4: test_cuda_unique_ptr .............   Passed    0.26 sec
test 5
    Start 5: test_cuda_error

...

5: Running main() from /opt/ros/humble/src/gtest_vendor/src/gtest_main.cc
5: [==========] Running 4 tests from 1 test suite.
5: [----------] Global test environment set-up.
5: [----------] 4 tests from CudaError
5: [ RUN      ] CudaError.SuccessDoesNotThrow
5: [       OK ] CudaError.SuccessDoesNotThrow (0 ms)
5: [ RUN      ] CudaError.FailureThrowsRuntimeError
5: [       OK ] CudaError.FailureThrowsRuntimeError (50 ms)
5: [ RUN      ] CudaError.FailureMessageContainsErrorNameAndLocation
5: [       OK ] CudaError.FailureMessageContainsErrorNameAndLocation (0 ms)
5: [ RUN      ] CudaError.MacroForwardsFileAndLine
5: [       OK ] CudaError.MacroForwardsFileAndLine (0 ms)
5: [----------] 4 tests from CudaError (50 ms total)
5:
5: [----------] Global test environment tear-down
5: [==========] 4 tests from 1 test suite ran. (50 ms total)
5: [  PASSED  ] 4 tests.
5: -- run_test.py: return code 0

...

5/6 Test #5: test_cuda_error ..................   Passed    0.13 sec
test 6
    Start 6: test_cuda_blackboard_pubsub

...

6: Running main() from /opt/ros/humble/src/gtest_vendor/src/gtest_main.cc
6: [==========] Running 2 tests from 1 test suite.
6: [----------] Global test environment set-up.
6: [----------] 2 tests from CudaBlackboardPubSubTest
6: [ RUN      ] CudaBlackboardPubSubTest.SubscriberDiscoversPublisher
6: [WARN 1781573371.166062334] [cuda_blackboard_sub_node]: `user_stream` was not set or the legacy default stream was specified for the CudaBlackboardSubscriber of test_image. This causes process-wide synchronization after the callback executes, which may degrade performance. Moreover, if the subscribed data is consumed on a CUDA stream created with the `cudaStreamNonBlocking` flag, this may cause a use-after-free of the pointer. To avoid this, consider the following:
6:   - pass the stream to the CudaBlackboardSubscriber's constructor, and/or
6:   - perform proper synchronization on the stream in the callback
6: [       OK ] CudaBlackboardPubSubTest.SubscriberDiscoversPublisher (61 ms)
6: [ RUN      ] CudaBlackboardPubSubTest.PublishDeliversImageToSubscriber
6: [INFO 1781573371.252693964] [cuda_blackboard_pub_node]: Negotiating
6: [INFO 1781573371.252947479] [cuda_blackboard_sub_node]: A negotiation type succeeded, so the compatible callback will be disabled
6: [       OK ] CudaBlackboardPubSubTest.PublishDeliversImageToSubscriber (105 ms)
6: [----------] 2 tests from CudaBlackboardPubSubTest (166 ms total)
6:
6: [----------] Global test environment tear-down
6: [==========] 2 tests from 1 test suite ran. (166 ms total)
6: [  PASSED  ] 2 tests.
6: -- run_test.py: return code 0

...

6/6 Test #6: test_cuda_blackboard_pubsub ......   Passed    0.29 sec

100% tests passed, 0 tests failed out of 6

Label Time Summary:
gtest    =   1.47 sec*proc (6 tests)

Total Test time (real) =   1.47 sec
---
Finished <<< cuda_blackboard [1.52s]

Summary: 1 package finished [1.64s]

Remarks

Pre-Review Checklist for the PR Author

PR Author should check the checkboxes below when creating the PR.

  • Assign PR to reviewer

Checklist for the PR Reviewer

Reviewers should check the checkboxes below before approval.

  • Commits are properly organized and messages are according to the guideline
  • (Optional) Unit tests have been written for new behavior
  • PR title describes the changes

Post-Review Checklist for the PR Author

PR Author should check the checkboxes below before merging.

  • All open points are addressed and tracked via issues or tickets

CI Checks

  • Build and test for PR: Required to pass before the merge.

manato added 27 commits June 7, 2026 19:41
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
…eference

Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
…g sync

Replace the blocking cudaEventSynchronize() calls on the consumption/free
path with stream-ordered dependencies, so freeing memory no longer stalls the
host.

Albeit there is a fallback to capture operation dependencies using
`cudaStreamLegacy`, there still is a special case where the dependencies cannot
be fully captured; the combination of
- A cudaStreamNonBlocking stream consumes a CudaUniquePtr
- The stream is not provided to the ctor of CudaBlackboardSubscriber, and
- The stream doesn't correctly synchronize in the callback.

Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Since the CudaBlackboardPublisher has no access to the user-side cuda stream at
this moment, it is unable to record the event for securing complete of the data production
properly. So I left a TODO comment for future extension.

Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
…tribute

This detects deprecated API usage at compile time and warns about it

Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
…intcloud2.cpp and cuda_image.cpp

Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
- Create new one in the copy constructors
- Destroy the existing one then move in the move-assignment

Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
…ber as friend

Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
and remove functions not used anymore

Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
…sage_impl_detail`

Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Signed-off-by: Manato HIRABAYASHI <manato.hirabayashi@tier4.jp>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants