ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
2

Catkin Doesn't Play Nice With Google Mock

asked 2014-12-17 11:43:44 -0600

kyrofa gravatar image

updated 2014-12-17 11:55:07 -0600

My team is currently transitioning from Ubuntu 12.04 and ROS Fuerte to Ubuntu 14.04 and ROS Indigo. All of our software is heavily tested using gtest and gmock. The latter is proving particularly difficult during this migration.

In Ubuntu 12.04, the gtest package is source-only, so rosbuild's public.cmake is hard-coded to check for that and compile it as needed. However, gmock's package includes a compiled library, so we just needed to make sure we added it to our linker and we were good to go.

We didn't investigate any further at the time, but it turned out that this only worked out of pure luck. I've since learned that gmock is distributed with a version of gtest included, and _must use that version_. As luck would have it, the packages in the repos were in sync (i.e. the gtest version was the same as the version of gtest included in gmock).

I learned that because now it's biting us in Ubuntu 14.04. Gmock has changed to also be distributed as source-only, but of course it still includes a version of gtest. However, this time the version of gtest contained within gmock was _not_ in sync with the gtest package, so I spent some time tracking that down (ended up stealing a later version of the gtest package from the next Ubuntu release). Ideally I'd just uninstall the libgtest-dev package, but half the ROS packages depend upon it.

Anyway, in Indigo, Catkin still has the hard-coded logic to look in /usr/src/gtest/src for gtest's source, which is where the libgtest-dev installs it. However, that makes it downright impossible to link in gmock without some serious alterations to gmock. When using gmock, ideally one would simply add it to the CMakeLists.txt and use as well as gtest (since gmock pulls in gtest). However, we can't do that since Catkin automatically pulls in the libgtest-dev's version of gtest, and pulling in gmock just defines the libgtest and libgtest_main targets twice, which obviously doesn't fly.

I feel like my only option is to disable Catkin's testing and stop using Catkin's gtest macros and essentially roll my own version that uses gmock and its bundled gtest instead. Or move to another mocking framework, which would be... painful.

I know other people were using gtest and gmock in 12.04 and rosbuild, but I've seen _nothing_ for gmock and Catkin. What is everyone else doing?

edit retag flag offensive close merge delete

5 Answers

Sort by ยป oldest newest most voted
1

answered 2014-12-17 20:15:04 -0600

Dirk Thomas gravatar image

catkin currently only provides functions to support the user in using gtest.

We have added gmock support in a forked version but there these modifications are not easily deployable to ROS. The reason is that once any package is using gtest a later package within the same workspace can't use gmock since it requires to switch the gtest version being used (when the workspace is build without isolation.

The only viable option would be to remove the dependency on gtest and replacing it with gmock - even if packages only use gtest. Such a change could be considered for the next ROS distro (Jade). I would hesitate to backport such a severe change into a long-ago released ROS release simply for stability reasons.

Anyway, I don't think that your statement that catkin makes it "downright impossible" to use gmock is true. It does not provide any support for it but any package is "free" to use gmock and setup everything necessary for it on its own. The only thing you have to make sure is to "find" gtest (from within gmock) before finding catkin. In that case the whole logic in catkin to find gtest will be skipped ( https://github.com/ros/catkin/blob/80... ).

This approach will still have the caveat mentioned above when you try to build your package together with other packages without isolation.

edit flag offensive delete link more

Comments

According to catkin's gtest.cmake file, if gtest is found is still adds an imported lib called "gtest" and "gtest_main," which means at least with my knowledge of CMake, I can't build another target lib called "gtest" or "gtest_main". So are you suggesting I pre-build gtest and gmock?

kyrofa gravatar image kyrofa  ( 2014-12-18 11:15:46 -0600 )edit

For what it's worth, it would be a pretty simple change for catkin to check to see if /usr/src/gmock/gtest exists before the test for /usr/src/gtest, and would be backward compatible. Wouldn't it?

kyrofa gravatar image kyrofa  ( 2014-12-18 11:33:28 -0600 )edit

That would be a good option. But the path-based lookup is only the second resolve strategy. If the first (find_package(GTest QUIET)) is successful we are not even looking at these hard-coded paths.

I have created https://github.com/ros/catkin/issues/699 for using gmock together with catkin.

Dirk Thomas gravatar image Dirk Thomas  ( 2014-12-18 11:44:49 -0600 )edit

Correct me if I'm wrong, but if I follow the Ubuntu ROS install guide and install ros-indigo-desktop-full, it pulls in libgtest-dev. libgtest-dev is source-only-- find_package(GTest QUIET) will fail! Which means on a default Ubuntu install, you're _always_ using the second resolve strategy.

kyrofa gravatar image kyrofa  ( 2014-12-18 12:20:46 -0600 )edit

So again, the only way to supercede the default behavior is to use find_package(GTest QUIET) , which in my understanding requires a pre-built gtest, violating gtest recommendations ( https://code.google.com/p/googletest/... ).

kyrofa gravatar image kyrofa  ( 2014-12-18 13:00:36 -0600 )edit
2

answered 2017-01-17 08:07:26 -0600

alextoind gravatar image

updated 2017-02-06 08:27:13 -0600

Based on @otamachan answer, this is my working configuration on Ubuntu 16.04 with ROS Kinetic, gtest (libgtest-dev v1.7.0-4ubuntu1) and gmock (google-mock v1.7.0-18092013-1):

# Tests
if(CATKIN_ENABLE_TESTING)
  find_package(rostest REQUIRED)

  # explicit gmock build (set these paths properly!)
  include_directories(/usr/include/gmock /usr/src/gmock)
  find_library(GMOCK_LIBRARIES libgmock)
  if(NOT GMOCK_LIBRARIES)
    add_library(libgmock /usr/src/gmock/src/gmock-all.cc)
  endif()

  add_rostest_gtest(my_test
    test/my_test.test
    src/test/my_test.cpp
    ...
  )

  target_link_libraries(my_test
    libgmock
    ${catkin_LIBRARIES}
  )
endif()

It seems that the problem has been simplified since gmock does not include gtest anymore.


EDIT: as shown in the launchpad, the google-mock package for Ubuntu Xenial depends on libgtest-dev (>= 1.6.0). Actually it does not includes gtest even since Ubuntu 14.10 (Utopic Unicorn). Unfortunately, Ubuntu 14.04 is shipped with google-mock v1.6.0+svn437-0ubuntu5 (see the package) which includes gtest inside; indeed, it depends on nothing but python.


EDIT2: added a simple check to avoid multiple add_library(libgmock ...) from distinct packages.

edit flag offensive delete link more

Comments

gtest never included gmock. gmock includes / included (?) gtest.

Dirk Thomas gravatar image Dirk Thomas  ( 2017-01-24 12:40:13 -0600 )edit

@Dirk Thomas sorry for the typo, it's obviously that way - as shown in the other answer. Edited, thank you!

alextoind gravatar image alextoind  ( 2017-01-24 15:15:20 -0600 )edit

What about running ROS Indigo on Ubuntu 16.04 Xenial? Would this allow for the separation between Google test and Google mock packages to try this fix?

roboticom314 gravatar image roboticom314  ( 2017-02-01 12:22:52 -0600 )edit

ROS Indigo is not supported on Ubuntu Xenial. You'd need ROS Kinetic, instead.

joq gravatar image joq  ( 2017-02-01 14:11:24 -0600 )edit

@roboticom314 with Xenial you would be fine: it is not a matter of ROS version. However, @joq is right.

alextoind gravatar image alextoind  ( 2017-02-01 16:53:02 -0600 )edit
2

answered 2015-11-18 08:31:33 -0600

otamachan gravatar image

I build gmock manually and replace GTEST_LIBRARIES after find_package(catkin). This is not clean solution but it works in Ubuntu 14.04 and Indigo.

find_package(catkin REQUIRED)
...
# Build gmock
set(gmock_SOURCE_DIR /usr/src/gmock)
include_directories(${gmock_SOURCE_DIR}/include
                    ${gmock_SOURCE_DIR}
                    ${gmock_SOURCE_DIR}/gtest/include
                    ${gmock_SOURCE_DIR}/gtest)
add_library(gmock
            ${gmock_SOURCE_DIR}/gtest/src/gtest-all.cc
            ${gmock_SOURCE_DIR}/src/gmock-all.cc)
target_link_libraries(gmock pthread)
# Replace catkin variable
set(GTEST_LIBRARIES gmock)
...
catkin_add_gtest(${PROJECT_NAME}-test test/test_sample.cpp)
edit flag offensive delete link more
1

answered 2015-01-13 14:18:53 -0600

kyrofa gravatar image

It seems the only way to continue building GTest and GMock from source (as recommended by Google) is to patch Catkin to check for the presence of GMock before GTest. Such a change is contained within this pull request, and is backward-compatible.

edit flag offensive delete link more
0

answered 2019-03-15 16:46:59 -0600

As of this PR (which was merged in late 2017, should be in catkin versions 0.7.9 and later), the easiest way to add a GMock test is to use catkin_add_gmock instead of catkin_add_gtest, as seen in the docs.

edit flag offensive delete link more

Question Tools

3 followers

Stats

Asked: 2014-12-17 11:43:44 -0600

Seen: 3,396 times

Last updated: Mar 15 '19