From fe7aaf4d9410ddfaaca51fb845ef7ff2cf6c15a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Schw=C3=B6rer?= Date: Fri, 27 Apr 2018 13:45:54 +0200 Subject: [PATCH] Added a fake file writer (writes to string instead of file) (#1101) Added fake filer writer which writes the output to a string instead of a file. This will help writing tests for classes that use the file writer interface to write data. --- cartographer/BUILD.bazel | 35 +++++- cartographer/cloud/BUILD.bazel | 1 + cartographer/io/fake_file_writer.cc | 55 ++++++++++ cartographer/io/fake_file_writer.h | 50 +++++++++ cartographer/io/fake_file_writer_test.cc | 129 +++++++++++++++++++++++ 5 files changed, 266 insertions(+), 4 deletions(-) create mode 100644 cartographer/io/fake_file_writer.cc create mode 100644 cartographer/io/fake_file_writer.h create mode 100644 cartographer/io/fake_file_writer_test.cc diff --git a/cartographer/BUILD.bazel b/cartographer/BUILD.bazel index 23c0f98..7234213 100644 --- a/cartographer/BUILD.bazel +++ b/cartographer/BUILD.bazel @@ -48,6 +48,29 @@ cc_fix_config( visibility = ["//visibility:private"], ) +TEST_LIBRARY_SRCS = glob([ + "**/*test_helpers.cc", + "**/fake_*.cc", + "**/mock_*.cc", +]) + +TEST_LIBRARY_HDRS = glob([ + "**/*test_helpers.h", + "**/fake_*.h", + "**/mock_*.h", +]) + +cc_library( + name = "cartographer_test_library", + testonly = 1, + srcs = TEST_LIBRARY_SRCS, + hdrs = TEST_LIBRARY_HDRS, + deps = [ + ":cartographer", + "@com_google_googletest//:gtest", + ], +) + cc_library( name = "cartographer", srcs = glob( @@ -57,13 +80,16 @@ cc_library( exclude = [ "**/*_main.cc", "**/*_test.cc", - ], + ] + TEST_LIBRARY_SRCS, ), hdrs = [ "common/config.h", - ] + glob([ - "**/*.h", - ]), + ] + glob( + [ + "**/*.h", + ], + exclude = TEST_LIBRARY_HDRS, + ), copts = ["-Wno-sign-compare"], includes = ["."], deps = [ @@ -83,6 +109,7 @@ cc_library( data = ["//:configuration_files"], deps = [ ":cartographer", + ":cartographer_test_library", "@com_google_googletest//:gtest_main", ], ) for src in glob( diff --git a/cartographer/cloud/BUILD.bazel b/cartographer/cloud/BUILD.bazel index 8aa5ff5..537a361 100644 --- a/cartographer/cloud/BUILD.bazel +++ b/cartographer/cloud/BUILD.bazel @@ -94,6 +94,7 @@ cc_binary( tags = ["exclusive"], deps = [ ":cartographer_grpc", + "//cartographer:cartographer_test_library", "@com_google_googletest//:gtest_main", ], ) for src in glob( diff --git a/cartographer/io/fake_file_writer.cc b/cartographer/io/fake_file_writer.cc new file mode 100644 index 0000000..424a967 --- /dev/null +++ b/cartographer/io/fake_file_writer.cc @@ -0,0 +1,55 @@ +/* + * Copyright 2018 The Cartographer Authors + * + * 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 "cartographer/io/fake_file_writer.h" + +#include "glog/logging.h" +#include "gtest/gtest.h" + +namespace cartographer { +namespace io { + +FakeFileWriter::FakeFileWriter(const std::string& filename, + std::shared_ptr> content) + : is_closed_(false), content_(content), filename_(filename) { + CHECK(content != nullptr); +} + +bool FakeFileWriter::Write(const char* const data, const size_t len) { + EXPECT_FALSE(is_closed_); + content_->insert(content_->end(), data, data + len); + return true; +} + +bool FakeFileWriter::Close() { + EXPECT_FALSE(is_closed_); + is_closed_ = true; + return true; +} + +bool FakeFileWriter::WriteHeader(const char* const data, const size_t len) { + EXPECT_FALSE(is_closed_); + if (content_->size() < len) { + content_->resize(len); + } + std::copy(data, data + len, content_->begin()); + return true; +} + +std::string FakeFileWriter::GetFilename() { return filename_; } + +} // namespace io +} // namespace cartographer diff --git a/cartographer/io/fake_file_writer.h b/cartographer/io/fake_file_writer.h new file mode 100644 index 0000000..fb3d5e4 --- /dev/null +++ b/cartographer/io/fake_file_writer.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 The Cartographer Authors + * + * 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 CARTOGRAPHER_IO_FAKE_FILE_WRITER_H_ +#define CARTOGRAPHER_IO_FAKE_FILE_WRITER_H_ + +#include +#include +#include + +#include "cartographer/io/file_writer.h" + +namespace cartographer { +namespace io { + +// Fakes a FileWriter by just writing the data to a std::vector. +class FakeFileWriter : public FileWriter { + public: + FakeFileWriter(const std::string& filename, + std::shared_ptr> content); + ~FakeFileWriter() override = default; + + bool WriteHeader(const char* data, size_t len) override; + bool Write(const char* data, size_t len) override; + bool Close() override; + std::string GetFilename() override; + + private: + bool is_closed_; + std::shared_ptr> content_; + std::string filename_; +}; + +} // namespace io +} // namespace cartographer + +#endif // CARTOGRAPHER_IO_FAKE_FILE_WRITER_H_ diff --git a/cartographer/io/fake_file_writer_test.cc b/cartographer/io/fake_file_writer_test.cc new file mode 100644 index 0000000..6189b92 --- /dev/null +++ b/cartographer/io/fake_file_writer_test.cc @@ -0,0 +1,129 @@ +/* + * Copyright 2018 The Cartographer Authors + * + * 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 + +#include "cartographer/io/fake_file_writer.h" +#include "glog/logging.h" +#include "gtest/gtest.h" + +namespace cartographer { +namespace io { +namespace { + +std::string toString(const std::vector& data) { + return std::string(data.data(), data.size()); +} + +TEST(FakeFileWriter, Filename) { + auto content = std::make_shared>(); + FakeFileWriter writer("file", content); + EXPECT_EQ("file", writer.GetFilename()); +} + +TEST(FakeFileWriter, CloseStream) { + auto content = std::make_shared>(); + FakeFileWriter writer("file", content); + EXPECT_TRUE(writer.Close()); + EXPECT_EQ("", toString(*content)); +} + +TEST(FakeFileWriter, WriteHeader) { + auto content = std::make_shared>(); + const std::string header("dummy header"); + const std::string header_2("dummy header 2"); + FakeFileWriter writer("file", content); + + EXPECT_TRUE(writer.WriteHeader(header.c_str(), header.size())); + EXPECT_EQ("dummy header", toString(*content)); + + EXPECT_TRUE(writer.WriteHeader(header_2.c_str(), header_2.size())); + EXPECT_EQ("dummy header 2", toString(*content)); + + EXPECT_TRUE(writer.Close()); + EXPECT_EQ("dummy header 2", toString(*content)); +} + +TEST(FakeFileWriter, Write) { + auto content = std::make_shared>(); + const std::vector data_stream = {"data 1", "data 2"}; + FakeFileWriter writer("file", content); + + for (const auto& data : data_stream) { + EXPECT_TRUE(writer.Write(data.c_str(), data.size())); + } + + EXPECT_EQ("data 1data 2", toString(*content)); + EXPECT_TRUE(writer.Close()); + EXPECT_EQ("data 1data 2", toString(*content)); +} + +TEST(FakeFileWriter, HeaderAndWrite) { + auto content = std::make_shared>(); + const std::string header("dummy header"); + const std::vector data_stream = {"data 1", "data 2"}; + FakeFileWriter writer("file", content); + + EXPECT_TRUE(writer.WriteHeader(header.c_str(), header.size())); + EXPECT_EQ("dummy header", toString(*content)); + + for (const auto& data : data_stream) { + EXPECT_TRUE(writer.Write(data.c_str(), data.size())); + } + + EXPECT_TRUE(writer.Close()); + EXPECT_EQ("dummy headerdata 1data 2", toString(*content)); +} + +TEST(FakeFileWriter, WriteTerminatedString) { + auto content = std::make_shared>(); + std::vector data_stream = {'d', 'a', 't', 'a', '\0', ' ', '1'}; + FakeFileWriter writer("file", content); + EXPECT_TRUE(writer.Write(data_stream.data(), data_stream.size())); + EXPECT_EQ(data_stream, *content); +} + +TEST(FakeFileWriter, WriteTerminatedHeaderString) { + auto content = std::make_shared>(); + std::vector header = {'h', 'e', 'a', 'd', '\0', ' ', 'e', 'r'}; + FakeFileWriter writer("file", content); + EXPECT_TRUE(writer.WriteHeader(header.data(), header.size())); + EXPECT_EQ(header, *content); +} + +TEST(FakeFileWriter, HeaderAndWriteTerminatedString) { + auto content = std::make_shared>(); + std::vector header = {'d', 'a', 't', 'a', '\0', ' ', '1'}; + std::vector data = {'h', 'e', 'a', 'd', '\0', ' ', 'e', 'r'}; + + FakeFileWriter writer("file", content); + EXPECT_TRUE(writer.WriteHeader(header.data(), header.size())); + EXPECT_EQ(header, *content); + + EXPECT_TRUE(writer.Write(data.data(), data.size())); + + std::vector expected_output = header; + expected_output.insert(expected_output.end(), data.begin(), data.end()); + + EXPECT_EQ(expected_output, *content); + + EXPECT_TRUE(writer.Close()); + EXPECT_EQ(expected_output, *content); +} + +} // namespace +} // namespace io +} // namespace cartographer