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

Display bag summary using ros2 bag info #42

Closed
wants to merge 82 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
822bccd
GH-77 Introduce bagfile struct
Martin-Idel-SI Sep 13, 2018
84f9210
GH-78 Add yaml-cpp dependency and test for yaml reader/writer
Martin-Idel-SI Sep 13, 2018
4a1ef3e
GH-78 Implement methods to write and read yaml file
Martin-Idel-SI Sep 14, 2018
c2a4118
GH-77 Use std::chrono for time duration
Martin-Idel-SI Sep 14, 2018
a2a2478
GH-77 Further improve storage info struct
Martin-Idel-SI Sep 17, 2018
0bdbd89
GH-78 Fix windows support
Martin-Idel-SI Sep 17, 2018
a4f4897
GH-78 Cleanup: rename test file
anhosi Sep 17, 2018
98c13cd
GH-79 Provide storage metadata in writable storage
greimela-si Sep 19, 2018
51ed601
GH-79 Remove obsolete BagInfo struct
greimela-si Sep 20, 2018
453cd85
GH-79 Calculate file size in sqlite3::get_metadata()
greimela-si Sep 20, 2018
cd91d98
GH-80 Write yaml file before shutdown
Martin-Idel-SI Sep 24, 2018
e3b8dd8
GH-80 Provide factory for writer to reduce exposed interfaces
Martin-Idel-SI Sep 24, 2018
509a596
GH-81 Add info() method to rosbag2::SequentialReader
botteroa-si Sep 24, 2018
eeeab4b
GH-91 Hide metadata path inside metadata_io
greimela-si Sep 24, 2018
bc80cec
GH-90 Complete implementation of CLI for info
botteroa-si Sep 24, 2018
07f631b
GH-81 Add MetadataIO class and use it instead of the free methods wri…
botteroa-si Sep 24, 2018
dbfd1ac
GH-81 Add test for SequentialReader::info() and minor refactoring
botteroa-si Sep 25, 2018
8a8a42e
GH-81 Fix test_metadata_serialization and cpplint
botteroa-si Sep 25, 2018
b0851fc
GH-81 Move yaml converter function from metadata_io.hpp to cpp file
botteroa-si Sep 25, 2018
783521c
GH-81 Fix Windows build
botteroa-si Sep 25, 2018
9618c45
GH-81 Add Info class and refactor MetadataIO
botteroa-si Sep 25, 2018
2cdeadf
GH-81 Update test_info
botteroa-si Sep 25, 2018
54d5bfe
GH-91 Identify bags using directory instead of file
greimela-si Sep 25, 2018
9c7fb21
GH-91 Remove file size from BagMetadata
greimela-si Sep 25, 2018
7a5bb07
GH-91 Fix metadata test on windows
greimela-si Sep 25, 2018
5abd538
GH-90 Add info end-to-end test
botteroa-si Sep 25, 2018
166b18b
GH-80 Add test to metadata_serialization with explicit yaml file
Martin-Idel-SI Sep 25, 2018
ca97392
GH-80 Implement Writer using metadataio
Martin-Idel-SI Sep 25, 2018
143a0fe
GH-80 Fix build after rebase
Martin-Idel-SI Sep 25, 2018
13e2319
GH-80 Skip failing test for now
Martin-Idel-SI Sep 25, 2018
e679186
GH-80 Fix metadata test
Martin-Idel-SI Sep 25, 2018
0082dfa
GH-90 Introduce factory in rosbag2 transport
Martin-Idel-SI Sep 25, 2018
a1575bb
GH-90 Stabilize info end-to-end test
botteroa-si Sep 26, 2018
278b10c
GH-90 Try to fix Windows build
botteroa-si Sep 26, 2018
35a9f98
GH-80 Implement reader and writer as RAII
Martin-Idel-SI Sep 26, 2018
bfc71d5
GH-90 Introduce storage interface to mock rosbag2_storage
Martin-Idel-SI Sep 26, 2018
1e8749a
GH-90 Use factory also in rosbag2::Info
Martin-Idel-SI Sep 26, 2018
7d043bc
GH-90 Delete superfluous test dependency on default plugins
Martin-Idel-SI Sep 26, 2018
680eb50
GH-90 Rename metadata_io
Martin-Idel-SI Sep 26, 2018
3918683
GH-81 Move metadata integration test to rosbag2 info test
Martin-Idel-SI Sep 26, 2018
c92714b
GH-90 Add virtual destructor to rosbag2_factory
Martin-Idel-SI Sep 26, 2018
17ac191
GH-92 Check return code of ros2 bag call, and extract common test fix…
botteroa-si Sep 26, 2018
3795f5f
GH-81 Better help for record CLI
greimela-si Sep 26, 2018
821a44d
GH-81 Metadata versioning, better filesystem helper
greimela-si Sep 26, 2018
96e719a
GH-82 Introduce first bag printing
Martin-Idel-SI Sep 26, 2018
8e960f9
GH-90 Remove unused assignment in info.py
botteroa-si Sep 26, 2018
4a048b9
GH-78 Fix bug in BagMetadata writing when bagfile is empty
greimela-si Sep 26, 2018
002f332
GH-91 Rename record option --uri to --output
greimela-si Sep 26, 2018
3adb45f
GH-90 Make names in rosbag2_storage consistent
Martin-Idel-SI Sep 26, 2018
75746f3
GH-91 Fix uncrustify
Martin-Idel-SI Sep 26, 2018
34f807c
GH-90 Extract helper methods for process execution
botteroa-si Sep 26, 2018
2bdf8af
GH-93 Extract Recorder from rosbag2_transport class
greimela-si Sep 27, 2018
8aca5ab
GH-93 Disable info e2e test until it is implementable
greimela-si Sep 27, 2018
e15da88
GH-90 Fix Windows build
botteroa-si Sep 27, 2018
75b5270
GH-93 Remove unused method from filesystem_helper
greimela-si Sep 27, 2018
d208e4e
GH-93 Extend filesystem helper to determine directory size
greimela-si Sep 27, 2018
15decca
GH-80 Refactor storage_factoy_impl for clarity
Martin-Idel-SI Sep 27, 2018
fb52ec4
GH-93 Print bag size on info
greimela-si Sep 27, 2018
b140392
GH-93 Fix string import on linux
greimela-si Sep 27, 2018
819cb34
GH-90 Improve comment in test justifying include order
Martin-Idel-SI Sep 27, 2018
5ea9ede
GH-93 Add tests for filesystem helper
greimela-si Sep 27, 2018
41d9163
GH-93 Fix bag size calculation on Windows
greimela-si Sep 27, 2018
4ed455e
GH-82 Refactor printing of bag info and format times to resamble outp…
botteroa-si Sep 27, 2018
c964244
GH-90 Update and Re-enable info end-to-end test
botteroa-si Sep 27, 2018
b41eb91
GH-82 Move info formatting methods from transport to rosbag2::Info
botteroa-si Sep 27, 2018
2412aec
GH-82 Fix Windows build
botteroa-si Sep 27, 2018
8024ab3
GH-82 Avoid crash when trying to display info of bag with no topics
botteroa-si Sep 27, 2018
103c74d
GH-82 Refactor printing of files and topics and extract Formatter class
botteroa-si Sep 28, 2018
36a27f1
GH-95 move assertion on exit code into tests
anhosi Sep 28, 2018
bfd15b8
GH-95 make info fail gracefully if bag does not exist
anhosi Sep 28, 2018
dd41882
GH-95 make play fail gracefully if the bag file does not exist
anhosi Sep 28, 2018
2c0ff88
GH-82 Correct formatting of file size and add tests for Formatter
botteroa-si Sep 28, 2018
0aced8b
GH-82 Refactor formatting of time and fix Windows warning (avoid use …
botteroa-si Sep 28, 2018
39c1f28
GH-94 Exit with errorcode on ros2 bag record error
greimela-si Sep 28, 2018
751a7d1
GH-82 Use correct symbols for file sizes units
botteroa-si Sep 28, 2018
e2c3c32
Remove temporary_dir fixture from rosbag2 and use the one in rosbag_t…
botteroa-si Sep 28, 2018
949273b
GH-94 Add tests for ros2 bag record error cases
greimela-si Sep 28, 2018
f8e26ea
GH-82 Rename 'encoding' BagMetadata field to 'storage_format', as pre…
botteroa-si Oct 1, 2018
0663eb5
GH-94 Show error message if output dir already exists (on record)
greimela-si Oct 1, 2018
de9b21c
GH-82 Use std::endl instead of \n
botteroa-si Oct 1, 2018
9fc449d
GH-82 Move Formatter class from rosbag2 to rosbag2_transport and refa…
botteroa-si Oct 1, 2018
d57fa23
Delete fixture in rosbag2_storage
Martin-Idel-SI Oct 4, 2018
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
Prev Previous commit
Next Next commit
GH-80 Write yaml file before shutdown
- Use interface to make writing optional in tests
  • Loading branch information
Martin-Idel-SI authored and greimela-si committed Sep 28, 2018
commit cd91d986671dac6688c562a3eb6c6f81057dff7d
9 changes: 8 additions & 1 deletion rosbag2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ find_package(rosidl_generator_cpp REQUIRED)
add_library(${PROJECT_NAME} SHARED
src/rosbag2/sequential_reader.cpp
src/rosbag2/typesupport_helpers.cpp
src/rosbag2/writer.cpp)
src/rosbag2/writer_impl.cpp)

ament_target_dependencies(${PROJECT_NAME}
ament_index_cpp
Expand Down Expand Up @@ -71,6 +71,13 @@ if(BUILD_TESTING)
if(TARGET rosbag2_typesupport_helpers_test)
target_link_libraries(rosbag2_typesupport_helpers_test rosbag2)
endif()

ament_add_gmock(test_writer
test/rosbag2/test_writer.cpp
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
if(TARGET test_writer)
target_link_libraries(test_writer rosbag2)
endif()
endif()

ament_package()
20 changes: 4 additions & 16 deletions rosbag2/include/rosbag2/writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,6 @@
#include "rosbag2/types.hpp"
#include "rosbag2/visibility_control.hpp"

// This is necessary because of using stl types here. It is completely safe, because
// a) the member is not accessible from the outside
// b) there are no inline functions.
#ifdef _WIN32
# pragma warning(push)
# pragma warning(disable:4251)
#endif

namespace rosbag2
{

Expand All @@ -42,15 +34,15 @@ namespace rosbag2
class ROSBAG2_PUBLIC Writer
{
public:
virtual ~Writer();
virtual ~Writer() = default;

/**
* Opens a new bagfile and prepare it for writing messages. The bagfile must not exist.
* This must be called before any other function is used.
*
* \param options Options to configure the storage
*/
virtual void open(const StorageOptions & options);
virtual void open(const StorageOptions & options) = 0;

/**
* Create a new topic in the underlying storage. Needs to be called for every topic used within
Expand All @@ -59,19 +51,15 @@ class ROSBAG2_PUBLIC Writer
* \param topic_with_type name and type identifier of topic to be created
* \throws runtime_error if the Writer is not open.
*/
virtual void create_topic(const TopicWithType & topic_with_type);
virtual void create_topic(const TopicWithType & topic_with_type) = 0;

/**
* Write a message to a bagfile. The topic needs to have been created before writing is possible.
*
* \param message to be written to the bagfile
* \throws runtime_error if the Writer is not open.
*/
virtual void write(std::shared_ptr<SerializedBagMessage> message);

private:
rosbag2_storage::StorageFactory factory_;
std::shared_ptr<rosbag2_storage::storage_interfaces::ReadWriteInterface> storage_;
virtual void write(std::shared_ptr<SerializedBagMessage> message) = 0;
};

} // namespace rosbag2
Expand Down
85 changes: 85 additions & 0 deletions rosbag2/include/rosbag2/writer_impl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright 2018, Bosch Software Innovations GmbH.
//
// 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 ROSBAG2__WRITER_IMPL_HPP_
#define ROSBAG2__WRITER_IMPL_HPP_

#include <memory>
#include <string>

#include "rosbag2_storage/storage_factory.hpp"
#include "rosbag2_storage/storage_interfaces/read_write_interface.hpp"
#include "rosbag2/storage_options.hpp"
#include "rosbag2/types.hpp"
#include "rosbag2/visibility_control.hpp"
#include "rosbag2/writer.hpp"

// This is necessary because of using stl types here. It is completely safe, because
// a) the member is not accessible from the outside
// b) there are no inline functions.
#ifdef _WIN32
# pragma warning(push)
# pragma warning(disable:4251)
#endif

namespace rosbag2
{

/**
* The Writer allows writing messages to a new bag. For every topic, information about its type
* needs to be added before writing the first message.
*/
class ROSBAG2_PUBLIC WriterImpl : public Writer
{
public:
~WriterImpl() override;

/**
* Opens a new bagfile and prepare it for writing messages. The bagfile must not exist.
* This must be called before any other function is used.
*
* \param options Options to configure the storage
*/
void open(const StorageOptions & options) override;

/**
* Create a new topic in the underlying storage. Needs to be called for every topic used within
* a message which is passed to write(...).
*
* \param topic_with_type name and type identifier of topic to be created
* \throws runtime_error if the Writer is not open.
*/
void create_topic(const TopicWithType & topic_with_type) override;

/**
* Write a message to a bagfile. The topic needs to have been created before writing is possible.
*
* \param message to be written to the bagfile
* \throws runtime_error if the Writer is not open.
*/
void write(std::shared_ptr<SerializedBagMessage> message) override;

private:
rosbag2::StorageOptions options_;
rosbag2_storage::StorageFactory factory_;
std::shared_ptr<rosbag2_storage::storage_interfaces::ReadWriteInterface> storage_;
};

} // namespace rosbag2

#ifdef _WIN32
# pragma warning(pop)
#endif

#endif // ROSBAG2__WRITER_IMPL_HPP_
1 change: 1 addition & 0 deletions rosbag2/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>test_msgs</test_depend>
<test_depend>rosbag2_storage_default_plugins</test_depend>

<export>
<build_type>ament_cmake</build_type>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,33 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include "rosbag2/writer.hpp"
#include "rosbag2/writer_impl.hpp"

#include <memory>
#include <string>

#include "rosbag2_storage/metadata_io.hpp"
#include "rosbag2/storage_options.hpp"

namespace rosbag2
{

Writer::~Writer()
WriterImpl::~WriterImpl()
{
rosbag2_storage::write_metadata(options_.uri + "metadata.yaml", storage_->get_metadata());
storage_.reset(); // Necessary to ensure that the writer is destroyed before the factory
}

void Writer::open(const StorageOptions & options)
void WriterImpl::open(const StorageOptions & options)
{
storage_ = factory_.open_read_write(options.uri, options.storage_id);
if (!storage_) {
throw std::runtime_error("No storage could be initialized. Abort");
}
options_ = options;
}

void Writer::create_topic(const TopicWithType & topic_with_type)
void WriterImpl::create_topic(const TopicWithType & topic_with_type)
{
if (!storage_) {
throw std::runtime_error("Bag is not open. Call open() before writing.");
Expand All @@ -44,7 +47,7 @@ void Writer::create_topic(const TopicWithType & topic_with_type)
storage_->create_topic(topic_with_type);
}

void Writer::write(std::shared_ptr<SerializedBagMessage> message)
void WriterImpl::write(std::shared_ptr<SerializedBagMessage> message)
{
if (!storage_) {
throw std::runtime_error("Bag is not open. Call open() before writing.");
Expand Down
103 changes: 103 additions & 0 deletions rosbag2/test/rosbag2/temporary_directory_fixture.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright 2018, Bosch Software Innovations GmbH.
//
// 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 ROSBAG2__TEMPORARY_DIRECTORY_FIXTURE_HPP_
#define ROSBAG2__TEMPORARY_DIRECTORY_FIXTURE_HPP_

#include <gmock/gmock.h>

#include <string>

#ifdef _WIN32
# include <direct.h>
# include <Windows.h>
#else
# include <unistd.h>
# include <sys/types.h>
# include <dirent.h>
#endif

using namespace ::testing; // NOLINT

class TemporaryDirectoryFixture : public Test
{
public:
static void SetUpTestCase()
{
char template_char[] = "tmp_test_dir.XXXXXX";
#ifdef _WIN32
char temp_path[255];
GetTempPathA(255, temp_path);
_mktemp_s(template_char, strnlen(template_char, 20) + 1);
temporary_dir_path_ = std::string(temp_path) + std::string(template_char);
_mkdir(temporary_dir_path_.c_str());
#else
char * dir_name = mkdtemp(template_char);
temporary_dir_path_ = dir_name;
#endif
}

static void TearDownTestCase()
{
remove_directory_recursively(temporary_dir_path_);
}

static void remove_directory_recursively(const std::string & directory_path)
{
#ifdef _WIN32
// We need a string of type PCZZTSTR, which is a double null terminated char ptr
size_t length = strlen(directory_path.c_str());
TCHAR * temp_dir = new TCHAR[length + 2];
memcpy(temp_dir, temporary_dir_path_.c_str(), length);
temp_dir[length] = 0;
temp_dir[length + 1] = 0; // double null terminated

SHFILEOPSTRUCT file_options;
file_options.hwnd = nullptr;
file_options.wFunc = FO_DELETE; // delete (recursively)
file_options.pFrom = temp_dir;
file_options.pTo = nullptr;
file_options.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; // do not prompt user
file_options.fAnyOperationsAborted = FALSE;
file_options.lpszProgressTitle = nullptr;
file_options.hNameMappings = nullptr;

SHFileOperation(&file_options);
delete[] temp_dir;
#else
DIR * dir = opendir(directory_path.c_str());
if (!dir) {
return;
}
struct dirent * directory_entry;
while ((directory_entry = readdir(dir)) != nullptr) {
// Make sure to not call ".." or "." entries in directory (might delete everything)
if (strcmp(directory_entry->d_name, ".") != 0 && strcmp(directory_entry->d_name, "..") != 0) {
if (directory_entry->d_type == DT_DIR) {
remove_directory_recursively(directory_path + "/" + directory_entry->d_name);
}
remove((directory_path + "/" + directory_entry->d_name).c_str());
}
}
closedir(dir);
remove(temporary_dir_path_.c_str());
#endif
}

static std::string temporary_dir_path_;
};

std::string TemporaryDirectoryFixture::temporary_dir_path_ = ""; // NOLINT

#endif // ROSBAG2__TEMPORARY_DIRECTORY_FIXTURE_HPP_
55 changes: 55 additions & 0 deletions rosbag2/test/rosbag2/test_writer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2018, Bosch Software Innovations GmbH.
//
// 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.

#include <gmock/gmock.h>

#include <chrono>
#include <fstream>
#include <string>
#include <thread>

#include "rosbag2/storage_options.hpp"
#include "rosbag2/writer_impl.hpp"
#include "temporary_directory_fixture.hpp"

using namespace ::testing; // NOLINT
using namespace std::chrono_literals; // NOLINT

void write_file(const std::string & uri)
{
rosbag2::StorageOptions options = {uri, "sqlite3"};
rosbag2::WriterImpl writer;
writer.open(options);
writer.create_topic({"/string_topic", "topic/Type"});
}

std::string get_yaml_content(const std::string & filename)
{
std::ifstream read_file(filename);
std::ostringstream ss;
ss << read_file.rdbuf();
return ss.str();
}

TEST_F(TemporaryDirectoryFixture, writer_writes_correct_yaml_at_shutdown) {
write_file(temporary_dir_path_ + "/test.bag");

std::string expected_start("rosbag2_bagfile_information:"
"\n storage_identifier: sqlite3"
"\n encoding: cdr");

// TODO(Martin-Idel-SI): This is not yet the correct file name
std::string actual_yaml = get_yaml_content(temporary_dir_path_ + "/test.bagmetadata.yaml");
ASSERT_THAT(actual_yaml, StartsWith(expected_start));
}
Loading