-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Complete rcutils API coverage #272
Conversation
0fb4e3b
to
bcb394d
Compare
This isn't PR material just yet, but I wanted to open it early enough for folks to take a look at how tests are looking like, and, ideally, compare it side-by-side with @brawner's fault injection tooling. There are cases that definitely suit mocking conceptually (e.g. dealing with bad system clocks), others not so much (e.g. failing a finalization). |
4233dee
to
c9d722a
Compare
Total coverage is over 95%, but there're places where it is still below that mark. Those places were left out on purpose, and can be split into three (3) groups:
|
test/mocking_utils.hpp
Outdated
#if !defined(_WIN32) | ||
#if defined(__MACH__) | ||
|
||
class fake_clock : unique_in_scope<fake_clock> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fake_*
isn't a very helpful naming style for all these classes. What about rcutils_mock_*
or something that helps people get where it's coming from and what its use is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Being an internal testing tool, I didn't see the need to standardize their names. But moving them out into rcpputils
we have to.
test/mocking_utils.hpp
Outdated
|
||
#else // defined(__MACH__) | ||
|
||
class fake_clock : unique_in_scope<fake_clock> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct me if I'm wrong, but the only difference between these same class definitions is that do_clock_get_time returns a kern_return_t vs an int? Can you consolidate these differencese to a much smaller #if defined
block to reduce duplicated code? I think some of the other classes can be consolidated in a similar way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you consolidate these differences to a much smaller #if defined block to reduce duplicated code?
In this particular case, yes we can. A few using
directives can go a long way here.
In general, all "equivalent" classes can be consolidated into one, but in some cases I think interleaving all platform-specific details works against readability and thus I tend to split.
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
c9d722a
to
9e004d7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing work what you did here to improve Mimick
's usage! Left a couple of minor comments to consider before merging
fs.file_info(path).st_mode |= mocking_utils::filesystem::FileTypes::DIRECTORY; | ||
fs.exhaust_file_descriptors(); | ||
size = rcutils_calculate_directory_size(path, g_allocator); | ||
EXPECT_EQ(0u, size); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be checked here as well the output from the error or errno
? saw the rcutils_calculate_directory_size
code and it's printed with fprintf
to stderr
, should that be changed to rcutils_set_error
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could, but I'd keep changes to rcutils
implementation out of this PR. Same as before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, I can help you opening an enhancement issue targeting that if you'd like.
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
}; | ||
|
||
template<size_t N> | ||
class FileSystem |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know it's a bit subjective and I suggested the opposite on a different file, but this class doesn't seem to reuse much code across #ifdef blocks. Since it's the filesystem and each OS handles it differently, I think this file makes sense define the full class in single ifdef blocks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See 83140ec.
test/mocking_utils/patch.hpp
Outdated
mmk_mock_define(mock_type, ReturnType); | ||
}; | ||
|
||
template<size_t N, typename ReturnType, typename ArgType0> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it not possible to use a parameter pack like you do the trampoline struct for the mmk_mock_define calls? I'm not familiar with parameter packs, but I'm guessing you would have used them if it were actually possible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not because mmk_mock_define
is a macro that needs all the parameter types given as separate arguments at the preprocessing stage -- it won't play along with parameter packs.
test/mocking_utils/patch.hpp
Outdated
/// | ||
/// Useful to enable patching functions that take arguments whose types | ||
/// do not define basic comparison operators required by Mimick. | ||
#define MOCKING_UTILS_DEFINE_DUMMY_OPERATOR(type, op) \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggest: MOCKING_UTILS_BOOL_OPERATOR_RETURNS_FALSE
Just so when people see it in code, it's a bit clearer what this macro is doing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See 83140ec.
test/test_split.cpp
Outdated
@@ -19,6 +19,7 @@ | |||
#include "rcutils/error_handling.h" | |||
#include "rcutils/split.h" | |||
#include "rcutils/types/string_array.h" | |||
#include "rcutils/types/char_array.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix ordering
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That include actually shouldn't be there! It's a leftover, removed in 46a4c15.
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. Just a few minor comments.
explicit FileSystem(const std::string & scope) | ||
: opendir_mock_(MOCKING_UTILS_PATCH_TARGET(scope, opendir), | ||
MOCKING_UTILS_PATCH_PROXY(opendir)), | ||
#ifndef _GNU_SOURCE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also seems like a good candidate for combining with the ifndef block at line 88 below. Line 87 is the only line shared between the two cases.
test/test_filesystem.cpp
Outdated
@@ -201,6 +203,21 @@ TEST_F(TestFilesystemFixture, is_readable) { | |||
ASSERT_FALSE(nullptr == path); | |||
EXPECT_FALSE(rcutils_is_readable(path)); | |||
} | |||
{ | |||
char * path = rcutils_join_path(this->test_path, "dummy_nonexisting_file.txt", g_allocator); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
char * path = rcutils_join_path(this->test_path, "dummy_nonexisting_file.txt", g_allocator); | |
char * path = rcutils_join_path(this->test_path, "dummy_nonexistent_file.txt", g_allocator); |
test/test_filesystem.cpp
Outdated
} | ||
{ | ||
auto fs = mocking_utils::patch_filesystem("lib:rcutils"); | ||
const char * path = "dummy_non_readable_file.txt"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const char * path = "dummy_non_readable_file.txt"; | |
const char * path = "dummy_unreadable_file.txt"; |
test/test_filesystem.cpp
Outdated
@@ -232,6 +249,12 @@ TEST_F(TestFilesystemFixture, is_writable) { | |||
ASSERT_FALSE(nullptr == path); | |||
EXPECT_FALSE(rcutils_is_writable(path)); | |||
} | |||
{ | |||
auto fs = mocking_utils::patch_filesystem("lib:rcutils"); | |||
const char * path = "dummy_non_writable_file.txt"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const char * path = "dummy_non_writable_file.txt"; | |
const char * path = "dummy_unwritable_file.txt"; |
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Well, it appears that there's something very peculiar about how I'll exclude the tests that mock |
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Oh well, |
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Alright, thanks for the reviews guys! |
I'm not completely sure if this PR is the root cause, but there are a bunch of new test failures on the nightlies https://ci.ros2.org/view/nightly/job/nightly_linux_release/1633/ (all related to rcutils tests). |
Indeed. Looks like another corner case when mocking |
Since most of them started 3 days ago (see https://ci.ros2.org/view/nightly/job/nightly_linux_extra_rmw_release/797/testReport/ and https://ci.ros2.org/view/nightly/job/nightly_linux_thread_sanitizer/504/testReport/) I would think so. |
Fix PR'd in #274. |
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Precisely what the title says, filling the gaps with mocks. Depends on ros2/Mimick#7.