Skip to content
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

More spdlog tests #40

Merged
merged 8 commits into from
Jun 4, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions rcl_logging_spdlog/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@ if(BUILD_TESTING)
ament_lint_auto_find_test_dependencies()

find_package(ament_cmake_gtest REQUIRED)
find_package(rcpputils REQUIRED)
ament_add_gtest(test_logging_interface test/test_logging_interface.cpp)
if(TARGET test_logging_interface)
target_link_libraries(test_logging_interface ${PROJECT_NAME})
ament_target_dependencies(test_logging_interface rcpputils)
endif()
endif()

Expand Down
1 change: 1 addition & 0 deletions rcl_logging_spdlog/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<test_depend>rcpputils</test_depend>

<member_of_group>rcl_logging_packages</member_of_group>

Expand Down
127 changes: 127 additions & 0 deletions rcl_logging_spdlog/test/fixtures.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Copyright 2020 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef FIXTURES_HPP_
#define FIXTURES_HPP_

#include <rcpputils/filesystem_helper.hpp>
#include <rcutils/allocator.h>
#include <rcutils/error_handling.h>
#include <rcutils/get_env.h>
#include <rcutils/process.h>
#include <rcutils/types/string_array.h>

#include <string>

#include "gtest/gtest.h"

#ifdef _WIN32
#define popen _popen
#define pclose _pclose
#endif

namespace fs = rcpputils::fs;

class AllocatorTest : public ::testing::Test
{
public:
AllocatorTest()
: allocator(rcutils_get_default_allocator()),
bad_allocator(get_bad_allocator()),
invalid_allocator(rcutils_get_zero_initialized_allocator())
{
}

rcutils_allocator_t allocator;
rcutils_allocator_t bad_allocator;
rcutils_allocator_t invalid_allocator;

private:
static rcutils_allocator_t get_bad_allocator()
{
rcutils_allocator_t bad_allocator = rcutils_get_default_allocator();
bad_allocator.allocate = AllocatorTest::bad_malloc;
bad_allocator.reallocate = AllocatorTest::bad_realloc;
return bad_allocator;
}

static void * bad_malloc(size_t, void *)
{
return nullptr;
}

static void * bad_realloc(void *, size_t, void *)
{
return nullptr;
}
};

class LoggingTest : public AllocatorTest
{
public:
LoggingTest()
: AllocatorTest()
{
}

fs::path find_single_log()
{
fs::path log_dir = get_log_dir();
std::stringstream dir_command;
dir_command << "dir";
#ifdef _WIN32
dir_command << " /B";
#endif
dir_command << " " << (log_dir / get_expected_log_prefix()).string() << "*";

FILE * fp = popen(dir_command.str().c_str(), "r");
if (nullptr == fp) {
throw std::runtime_error("Failed to glob for log files");
}

char raw_line[2048];
cottsay marked this conversation as resolved.
Show resolved Hide resolved
while (fgets(raw_line, sizeof(raw_line), fp) != NULL) {
cottsay marked this conversation as resolved.
Show resolved Hide resolved
pclose(fp);

std::string line(raw_line);
fs::path line_path(line.substr(0, line.find_last_not_of(" \t\r\n") + 1));
// This should be changed once ros2/rcpputils#68 is resolved
return line_path.is_absolute() ? line_path : log_dir / line_path;
}

pclose(fp);
Copy link
Member Author

@cottsay cottsay Jun 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty much all of this should be replaced with properly iterating the directory content to find the log file, but that functionality isn't available in the filesystem helper. So either we need to implement it, or we need to bump to C++17, because this is kinda gross. (Post-Foxy)

throw std::runtime_error("No log files were found");
}

private:
std::string get_expected_log_prefix()
{
char * exe_name = rcutils_get_executable_name(allocator);
if (nullptr == exe_name) {
throw std::runtime_error("Failed to determine executable name");
}
std::stringstream prefix;
prefix << exe_name << "_" <<
cottsay marked this conversation as resolved.
Show resolved Hide resolved
rcutils_get_pid() << "_";
allocator.deallocate(exe_name, allocator.state);
Copy link
Member Author

@cottsay cottsay Jun 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should support get_executable_name in rcpputils to avoid the need for an allocator here. Post-Foxy, of course.

return prefix.str();
}

fs::path get_log_dir()
{
return fs::path(rcutils_get_home_dir()) / ".ros" / "log";
}
};

#endif // FIXTURES_HPP_
54 changes: 37 additions & 17 deletions rcl_logging_spdlog/test/test_logging_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,16 @@
#include <rcutils/allocator.h>
#include <rcutils/error_handling.h>
#include <rcutils/logging.h>
#include "rcl_logging_spdlog/logging_interface.h"
#include "gtest/gtest.h"

static void * bad_malloc(size_t, void *)
{
return nullptr;
}
#include <fstream>
#include <string>

TEST(logging_interface, init_invalid)
{
rcutils_allocator_t allocator = rcutils_get_default_allocator();
rcutils_allocator_t bad_allocator = rcutils_get_default_allocator();
rcutils_allocator_t invalid_allocator = rcutils_get_zero_initialized_allocator();
bad_allocator.allocate = bad_malloc;
#include "fixtures.hpp"
#include "gtest/gtest.h"
#include "rcl_logging_spdlog/logging_interface.h"

TEST_F(LoggingTest, init_invalid)
{
// Config files are not supported by spdlog
EXPECT_EQ(2, rcl_logging_external_initialize("anything", allocator));
rcutils_reset_error();
Expand All @@ -39,12 +34,37 @@ TEST(logging_interface, init_invalid)
rcutils_reset_error();
}

TEST(logging_interface, full_cycle)
TEST_F(LoggingTest, full_cycle)
{
rcutils_allocator_t allocator = rcutils_get_default_allocator();

ASSERT_EQ(0, rcl_logging_external_initialize(nullptr, allocator));
EXPECT_EQ(0, rcl_logging_external_set_logger_level(nullptr, RCUTILS_LOG_SEVERITY_INFO));
rcl_logging_external_log(RCUTILS_LOG_SEVERITY_INFO, nullptr, "Log Message");

std::stringstream expected_log;
for (int level = RCUTILS_LOG_SEVERITY_UNSET; level <= RCUTILS_LOG_SEVERITY_FATAL; level += 10) {
cottsay marked this conversation as resolved.
Show resolved Hide resolved
EXPECT_EQ(0, rcl_logging_external_set_logger_level(nullptr, level));

for (int severity = RCUTILS_LOG_SEVERITY_UNSET; severity <= RCUTILS_LOG_SEVERITY_FATAL;
severity += 10)
{
std::stringstream ss;
ss << "Message of severity " << severity << " at level " << level;
rcl_logging_external_log(severity, nullptr, ss.str().c_str());

if (severity >= level) {
expected_log << ss.str() << std::endl;
} else if (severity == 0 && level == 10) {
// This is a special case - not sure what the right behavior is
expected_log << ss.str() << std::endl;
Comment on lines +148 to +150
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I called this out on Slack - not sure what the expected behavior should be here, so for now I'm just asserting the current behavior.

}
}
}

EXPECT_EQ(0, rcl_logging_external_shutdown());

std::string log_file_path = find_single_log().string();
std::ifstream log_file(log_file_path);
std::stringstream actual_log;
actual_log << log_file.rdbuf();
EXPECT_EQ(
expected_log.str(),
actual_log.str()) << "Unexpected log contents in " << log_file_path;
}