Skip to content

Commit

Permalink
Add test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
umegane committed Oct 3, 2024
1 parent 8b8b8d6 commit 0146118
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 5 deletions.
11 changes: 11 additions & 0 deletions docs/internal/db_startup_sort_improvement.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@
* 現在の実装を確認し、それに合わせてロジックを組み込む必要がある。


## テストケースの作成

どのコミットの変更に対するテストケース作成が終わったか

* b01068c (origin/wip/log-0.7) cleanup: clang-tidy
* aed365d Make cursor class handle two streams
* 68480e0 Add flag to snapshot creation to skip entry removal
* 1a48442 Refactor to isolate testable units for easier testing => 完了



## 2024/10/03

なんとか動き始めたので、性能改善度合いを測定してみる。
Expand Down
22 changes: 17 additions & 5 deletions src/limestone/datastore_snapshot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,33 +309,45 @@ void create_compact_pwal(

std::set<std::string> assemble_snapshot_input_filenames(
const std::unique_ptr<compaction_catalog>& compaction_catalog,
const boost::filesystem::path& location) {
const boost::filesystem::path& location,
file_operations& file_ops) {
std::set<std::string> detached_pwals = compaction_catalog->get_detached_pwals();

std::set<std::string> filename_set;
boost::system::error_code error;
boost::filesystem::directory_iterator it(location, error);
boost::filesystem::directory_iterator end;

if (error) {
LOG_AND_THROW_IO_EXCEPTION("Failed to initialize directory iterator, path: " + location.string(), error);
}
for (; it != end; it.increment(error)) {

for (; it != end; file_ops.directory_iterator_next(it, error)) {
if (error) {
LOG_AND_THROW_IO_EXCEPTION("Failed to access directory entry, path: " + location.string(), error);
}
if (boost::filesystem::is_regular_file(it->path())) {
std::string filename = it->path().filename().string();
if (detached_pwals.find(filename) == detached_pwals.end() && filename != compaction_catalog::get_compacted_filename()) {
if (detached_pwals.find(filename) == detached_pwals.end()
&& filename != compaction_catalog::get_catalog_filename()
&& filename != compaction_catalog::get_compacted_filename()) {
filename_set.insert(filename);
}
}
}

return filename_set;
}

std::set<std::string> assemble_snapshot_input_filenames(
const std::unique_ptr<compaction_catalog>& compaction_catalog,
const boost::filesystem::path& location) {
real_file_operations file_ops;
return assemble_snapshot_input_filenames(compaction_catalog, location, file_ops);
}



} // namespace limestone::internal

namespace limestone::api {
using namespace limestone::internal;

Expand Down
5 changes: 5 additions & 0 deletions src/limestone/file_operations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ bool real_file_operations::exists(const boost::filesystem::path& p, boost::syste
return boost::filesystem::exists(p, ec);
}

void real_file_operations::directory_iterator_next(boost::filesystem::directory_iterator& it, boost::system::error_code& ec) {
it.increment(ec);
}


} // namespace limestone::internal


4 changes: 4 additions & 0 deletions src/limestone/file_operations.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ class file_operations {

// Checks if a file or directory exists (Boost)
virtual bool exists(const boost::filesystem::path& p, boost::system::error_code& ec) = 0;

// call directory_iterator::increment
virtual void directory_iterator_next(boost::filesystem::directory_iterator& it, boost::system::error_code& ec) = 0;
};

class real_file_operations : public file_operations {
Expand All @@ -125,6 +128,7 @@ class real_file_operations : public file_operations {
bool has_error(std::ifstream& file) override;

bool exists(const boost::filesystem::path& p, boost::system::error_code& ec) override;
void directory_iterator_next(boost::filesystem::directory_iterator& it, boost::system::error_code& ec) override;
};

} // namespace limestone::internal
Expand Down
165 changes: 165 additions & 0 deletions test/limestone/compaction/assemble_snapshot_input_filenames_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
* Copyright 2022-2024 Project Tsurugi.
*
* 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 <gtest/gtest.h>
#include <iostream>
#include <boost/filesystem.hpp>
#include "compaction_catalog.h"
#include "limestone/api/epoch_id_type.h"
#include "limestone/api/limestone_exception.h"

namespace limestone::internal {
// Forward declare the target function for testing
std::set<std::string> assemble_snapshot_input_filenames(
const std::unique_ptr<compaction_catalog>& compaction_catalog,
const boost::filesystem::path& location);
std::set<std::string> assemble_snapshot_input_filenames(
const std::unique_ptr<compaction_catalog>& compaction_catalog,
const boost::filesystem::path& location,
file_operations& file_ops);
}

namespace limestone::testing {

using limestone::internal::compacted_file_info;
using limestone::internal::compaction_catalog;
using limestone::api::limestone_io_exception;

class mock_file_operations : public limestone::internal::real_file_operations {
public:
void directory_iterator_next(boost::filesystem::directory_iterator& it, boost::system::error_code& ec) {
ec = boost::system::errc::make_error_code(boost::system::errc::permission_denied);
};
};

class assemble_snapshot_input_filenames_test : public ::testing::Test {
protected:
void SetUp() override {
// Set up temporary log directory for the test
if (system("rm -rf /tmp/assemble_snapshot_input_filenames_test") != 0) {
std::cerr << "Cannot remove directory" << std::endl;
}
if (system("mkdir -p /tmp/assemble_snapshot_input_filenames_test") != 0) {
std::cerr << "Cannot create directory" << std::endl;
}

// Initialize the compaction catalog with a valid log directory path
log_location_ = "/tmp/assemble_snapshot_input_filenames_test";
compaction_catalog_ = std::make_unique<compaction_catalog>(log_location_);
}

void TearDown() override {
// Clean up temporary log directory after the test
if (system("rm -rf /tmp/assemble_snapshot_input_filenames_test") != 0) {
std::cerr << "Cannot remove directory" << std::endl;
}
}

void clear_compaction_catalog() {
compacted_files_.clear();
detached_pwals_.clear();
}

void add_detached_pwals(const std::initializer_list<std::string>& pwals) {
detached_pwals_.insert(pwals.begin(), pwals.end());
compaction_catalog_->update_catalog_file(0, compacted_files_, detached_pwals_);
}

std::unique_ptr<compaction_catalog> compaction_catalog_;
boost::filesystem::path log_location_;

std::set<compacted_file_info> compacted_files_;
std::set<std::string> detached_pwals_;
};

TEST_F(assemble_snapshot_input_filenames_test, retrieves_filenames_correctly) {
// Prepare some files in the log location directory
std::ofstream(log_location_ / "pwal_0001");
std::ofstream(log_location_ / "pwal_0002");
std::ofstream(log_location_ / "pwal_0003");
std::ofstream(log_location_ / "pwal_0004");

// Simulate detached PWALs in the compaction catalog
add_detached_pwals({"pwal_0001", "pwal_0002"});

// Get the filenames that should be used for the snapshot
std::set<std::string> filenames;
filenames = assemble_snapshot_input_filenames(compaction_catalog_, log_location_);

// Ensure the correct files are retrieved
EXPECT_EQ(filenames.size(), 2);
EXPECT_NE(filenames.find("pwal_0003"), filenames.end());
EXPECT_NE(filenames.find("pwal_0004"), filenames.end());

// Ensure the detached PWALs are not included
std::ofstream(log_location_ / compaction_catalog::get_compacted_filename());
filenames = assemble_snapshot_input_filenames(compaction_catalog_, log_location_);
EXPECT_EQ(filenames.size(), 2);
EXPECT_NE(filenames.find("pwal_0003"), filenames.end());
EXPECT_NE(filenames.find("pwal_0004"), filenames.end());
}

TEST_F(assemble_snapshot_input_filenames_test, throws_exception_when_directory_does_not_exist) {
// Set a non-existent directory
boost::filesystem::path non_existent_directory = "/tmp/non_existent_directory";

// Check if an exception is thrown
try {
auto filenames = assemble_snapshot_input_filenames(compaction_catalog_, non_existent_directory);
FAIL() << "Expected an exception to be thrown";
} catch (const limestone_io_exception& e) {
// Check if the exception message contains the expected content
std::string expected_message = "Failed to initialize directory iterator, path:";
std::string actual_message = e.what();
std::cout << "Caught expected exception: " << actual_message << std::endl;
EXPECT_TRUE(actual_message.find(expected_message) != std::string::npos) << "Expected exception message to contain: " << expected_message;
} catch (...) {
FAIL() << "Expected a limestone_io_exception, but got a different exception";
}
}

TEST_F(assemble_snapshot_input_filenames_test, throws_exception_when_directory_iterator_increment) {
// Prepare some files in the log location directory
std::ofstream(log_location_ / "pwal_0001");
std::ofstream(log_location_ / "pwal_0002");
std::ofstream(log_location_ / "pwal_0003");
std::ofstream(log_location_ / "pwal_0004");

// Check if an exception is thrown
try {
mock_file_operations file_ops;
auto filenames = assemble_snapshot_input_filenames(compaction_catalog_,log_location_, file_ops);
FAIL() << "Expected an exception to be thrown";
} catch (const limestone_io_exception& e) {
// Check if the exception message contains the expected content
std::string expected_message = "Failed to access directory entry, path:";
std::string actual_message = e.what();
std::cout << "Caught expected exception: " << actual_message << std::endl;
EXPECT_TRUE(actual_message.find(expected_message) != std::string::npos) << "Expected exception message to contain: " << expected_message;
} catch (...) {
FAIL() << "Expected a limestone_io_exception, but got a different exception";
}
}

TEST_F(assemble_snapshot_input_filenames_test, handles_empty_directory) {
// No files are created in the directory
auto filenames = assemble_snapshot_input_filenames(compaction_catalog_, log_location_);

// Ensure that no files are retrieved
EXPECT_TRUE(filenames.empty());
}

} // namespace limestone::testing

0 comments on commit 0146118

Please sign in to comment.