summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorathanatos <rexludorum@gmail.com>2013-06-04 12:39:29 -0700
committerathanatos <rexludorum@gmail.com>2013-06-04 12:39:29 -0700
commit38d3c3cb5337104eb3dd9c3c4bdad1d7006b3e25 (patch)
tree34d0fd414cf4208f64e84d6e7735420d6e578ca9
parent8d948f6109e0ac600ab450e8d71b9747ab1044bd (diff)
parentb70868e007ffa56e0eabf22b4ca836327c5f82d4 (diff)
downloadceph-38d3c3cb5337104eb3dd9c3c4bdad1d7006b3e25.tar.gz
Merge pull request #340 from dachary/wip-5213
PGLog::merge_old_entry unit tests Reviewed-by: Sam Just <sam.just@inktank.com>
-rw-r--r--src/Makefile.am5
-rw-r--r--src/osd/PGLog.cc12
-rw-r--r--src/osd/PGLog.h7
-rw-r--r--src/test/osd/TestPGLog.cc546
4 files changed, 566 insertions, 4 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index ad80eac4a74..448797bde6a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -736,6 +736,11 @@ unittest_osd_types_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
unittest_osd_types_LDADD = libglobal.la libcommon.la $(PTHREAD_LIBS) -lm ${UNITTEST_LDADD} $(CRYPTO_LIBS) $(EXTRALIBS)
check_PROGRAMS += unittest_osd_types
+unittest_pglog_SOURCES = test/osd/TestPGLog.cc objclass/class_api.cc perfglue/disabled_heap_profiler.cc
+unittest_pglog_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
+unittest_pglog_LDADD = libosd.a $(LIBOS_LDA) $(LIBGLOBAL_LDA) ${UNITTEST_LDADD}
+check_PROGRAMS += unittest_pglog
+
unittest_gather_SOURCES = test/gather.cc
unittest_gather_LDADD = ${LIBGLOBAL_LDA} ${UNITTEST_LDADD}
unittest_gather_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
diff --git a/src/osd/PGLog.cc b/src/osd/PGLog.cc
index 638a78697db..cc897e00ae8 100644
--- a/src/osd/PGLog.cc
+++ b/src/osd/PGLog.cc
@@ -21,7 +21,7 @@
#define dout_subsys ceph_subsys_osd
-//////////////////// PGLog ////////////////////
+//////////////////// PGLog::IndexedLog ////////////////////
void PGLog::IndexedLog::split_into(
pg_t child_pgid,
@@ -103,6 +103,14 @@ ostream& PGLog::IndexedLog::print(ostream& out) const
//////////////////// PGLog ////////////////////
+void PGLog::clear() {
+ ondisklog.zero();
+ ondisklog.has_checksums = true;
+ ondisklog.divergent_priors.clear();
+ missing.clear();
+ log.zero();
+}
+
void PGLog::clear_info_log(
pg_t pgid,
const hobject_t &infos_oid,
@@ -251,7 +259,7 @@ void PGLog::proc_replica_log(ObjectStore::Transaction& t,
*
* return true if entry is not divergent.
*/
-bool PGLog::merge_old_entry(ObjectStore::Transaction& t, pg_log_entry_t& oe, pg_info_t& info, list<hobject_t>& remove_snap, bool &dirty_log)
+bool PGLog::merge_old_entry(ObjectStore::Transaction& t, const pg_log_entry_t& oe, const pg_info_t& info, list<hobject_t>& remove_snap, bool &dirty_log)
{
if (oe.soid > info.last_backfill) {
dout(20) << "merge_old_entry had " << oe << " : beyond last_backfill" << dendl;
diff --git a/src/osd/PGLog.h b/src/osd/PGLog.h
index 2cd85692c87..00bb72ad3ad 100644
--- a/src/osd/PGLog.h
+++ b/src/osd/PGLog.h
@@ -236,6 +236,9 @@ protected:
IndexedLog log;
public:
+
+ void clear();
+
//////////////////// get or set missing ////////////////////
const pg_missing_t& get_missing() const { return missing; }
@@ -353,8 +356,8 @@ public:
pg_missing_t& omissing, int from);
protected:
- bool merge_old_entry(ObjectStore::Transaction& t, pg_log_entry_t& oe,
- pg_info_t& info, list<hobject_t>& remove_snap, bool &dirty_log);
+ bool merge_old_entry(ObjectStore::Transaction& t, const pg_log_entry_t& oe,
+ const pg_info_t& info, list<hobject_t>& remove_snap, bool &dirty_log);
public:
void rewind_divergent_log(ObjectStore::Transaction& t, eversion_t newhead,
pg_info_t &info, list<hobject_t>& remove_snap,
diff --git a/src/test/osd/TestPGLog.cc b/src/test/osd/TestPGLog.cc
new file mode 100644
index 00000000000..10d32db22e2
--- /dev/null
+++ b/src/test/osd/TestPGLog.cc
@@ -0,0 +1,546 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic@dachary.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library Public License for more details.
+ *
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include "osd/PGLog.h"
+#include "common/ceph_argparse.h"
+#include "global/global_init.h"
+#include <gtest/gtest.h>
+
+class PGLogTest : public ::testing::Test, protected PGLog {
+public:
+ virtual void SetUp() { }
+
+ virtual void TearDown() {
+ clear();
+ }
+};
+
+TEST_F(PGLogTest, merge_old_entry) {
+ // entries > last_backfill are silently ignored
+ {
+ clear();
+
+ ObjectStore::Transaction t;
+ pg_log_entry_t oe;
+ pg_info_t info;
+ list<hobject_t> remove_snap;
+ bool dirty_log = false;
+
+ info.last_backfill = hobject_t();
+ info.last_backfill.hash = 1;
+ oe.soid.hash = 2;
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_TRUE(log.empty());
+ EXPECT_EQ(0U, ondisklog.length());
+
+ EXPECT_FALSE(merge_old_entry(t, oe, info, remove_snap, dirty_log));
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_TRUE(log.empty());
+ EXPECT_EQ(0U, ondisklog.length());
+ }
+
+ // a clone with no non-divergent log entry is deleted
+ {
+ clear();
+
+ ObjectStore::Transaction t;
+ pg_log_entry_t oe;
+ pg_info_t info;
+ list<hobject_t> remove_snap;
+ bool dirty_log = false;
+
+ oe.op = pg_log_entry_t::CLONE;
+
+ oe.soid.snap = CEPH_NOSNAP;
+ EXPECT_THROW(merge_old_entry(t, oe, info, remove_snap, dirty_log), FailedAssertion);
+ oe.soid.snap = 1U;
+ missing.add(oe.soid, eversion_t(), eversion_t());
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_TRUE(missing.have_missing());
+ EXPECT_TRUE(missing.is_missing(oe.soid));
+ EXPECT_TRUE(log.empty());
+ EXPECT_EQ(0U, ondisklog.length());
+
+ EXPECT_FALSE(merge_old_entry(t, oe, info, remove_snap, dirty_log));
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_EQ(oe.soid, remove_snap.front());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_TRUE(log.empty());
+ EXPECT_EQ(0U, ondisklog.length());
+ }
+
+ // the new entry (from the logs) old entry (from the log entry
+ // given in argument) have the same version : do nothing and return true.
+ {
+ clear();
+
+ ObjectStore::Transaction t;
+ pg_log_entry_t oe;
+ pg_info_t info;
+ list<hobject_t> remove_snap;
+ bool dirty_log = false;
+
+ oe.version = eversion_t(1,1);
+ log.add(oe);
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_EQ(1U, log.log.size());
+ EXPECT_EQ(0U, ondisklog.length());
+
+ EXPECT_TRUE(merge_old_entry(t, oe, info, remove_snap, dirty_log));
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_EQ(1U, log.log.size());
+ EXPECT_EQ(0U, ondisklog.length());
+ }
+
+ // the new entry (from the logs) has a version that is higher than
+ // the old entry (from the log entry given in argument) : do
+ // nothing and return false
+ {
+ clear();
+
+ ObjectStore::Transaction t;
+ pg_info_t info;
+ list<hobject_t> remove_snap;
+ bool dirty_log = false;
+
+ pg_log_entry_t ne;
+ ne.version = eversion_t(2,1);
+ log.add(ne);
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_EQ(1U, log.log.size());
+ EXPECT_EQ(ne.version, log.log.front().version);
+ EXPECT_EQ(0U, ondisklog.length());
+
+ // the newer entry ( from the logs ) can be DELETE
+ {
+ log.log.front().op = pg_log_entry_t::DELETE;
+ pg_log_entry_t oe;
+ oe.version = eversion_t(1,1);
+
+ EXPECT_FALSE(merge_old_entry(t, oe, info, remove_snap, dirty_log));
+ }
+
+ // if the newer entry is not DELETE, the object must be in missing
+ {
+ pg_log_entry_t &ne = log.log.front();
+ ne.op = pg_log_entry_t::MODIFY;
+ missing.add_next_event(ne);
+ pg_log_entry_t oe;
+ oe.version = eversion_t(1,1);
+
+ EXPECT_FALSE(merge_old_entry(t, oe, info, remove_snap, dirty_log));
+
+ missing.rm(ne.soid, ne.version);
+ }
+
+ // throw if the newer entry is not DELETE and not in missing
+ {
+ pg_log_entry_t &ne = log.log.front();
+ ne.op = pg_log_entry_t::MODIFY;
+ pg_log_entry_t oe;
+ oe.version = eversion_t(1,1);
+
+ EXPECT_THROW(merge_old_entry(t, oe, info, remove_snap, dirty_log), FailedAssertion);
+ }
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_EQ(1U, log.log.size());
+ EXPECT_EQ(ne.version, log.log.front().version);
+ EXPECT_EQ(0U, ondisklog.length());
+
+ }
+
+ // the new entry (from the logs) has a version that is lower than
+ // the old entry (from the log entry given in argument) and
+ // old and new are delete : do nothing and return false
+ {
+ clear();
+
+ ObjectStore::Transaction t;
+ pg_log_entry_t oe;
+ pg_info_t info;
+ list<hobject_t> remove_snap;
+ bool dirty_log = false;
+
+ pg_log_entry_t ne;
+ ne.version = eversion_t(1,1);
+ ne.op = pg_log_entry_t::DELETE;
+ log.add(ne);
+
+ oe.version = eversion_t(2,1);
+ oe.op = pg_log_entry_t::DELETE;
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_EQ(1U, log.log.size());
+ EXPECT_EQ(0U, ondisklog.length());
+
+ EXPECT_FALSE(merge_old_entry(t, oe, info, remove_snap, dirty_log));
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_EQ(1U, log.log.size());
+ EXPECT_EQ(0U, ondisklog.length());
+ }
+
+ // the new entry (from the logs) has a version that is lower than
+ // the old entry (from the log entry given in argument) and
+ // new is update :
+ // if the object is not already in missing, add it
+ // if the object is already in missing, revise the version it needs
+ // return false
+ {
+ __s32 ops[2] = { pg_log_entry_t::MODIFY, pg_log_entry_t::DELETE };
+ for (int i = 0; i < 2; i++) {
+ __s32 oe_op = ops[i];
+
+ clear();
+
+ ObjectStore::Transaction t;
+ pg_log_entry_t oe;
+ pg_info_t info;
+ list<hobject_t> remove_snap;
+ bool dirty_log = false;
+
+ pg_log_entry_t ne;
+ ne.version = eversion_t(1,1);
+ ne.op = pg_log_entry_t::MODIFY;
+ log.add(ne);
+
+ oe.version = eversion_t(2,1);
+ oe.op = oe_op;
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_EQ(1U, log.log.size());
+ EXPECT_EQ(0U, ondisklog.length());
+
+ eversion_t old_version(0, 0);
+ // if the object is not already in missing, add it
+ {
+ EXPECT_FALSE(merge_old_entry(t, oe, info, remove_snap, dirty_log));
+
+ EXPECT_TRUE(missing.is_missing(ne.soid, ne.version));
+ EXPECT_FALSE(missing.is_missing(ne.soid, old_version));
+ }
+ // if the object is already in missing, revise the version it needs
+ {
+ missing.revise_need(ne.soid, old_version);
+ EXPECT_TRUE(missing.is_missing(ne.soid, old_version));
+
+ EXPECT_FALSE(merge_old_entry(t, oe, info, remove_snap, dirty_log));
+
+ EXPECT_TRUE(missing.is_missing(ne.soid, ne.version));
+ EXPECT_FALSE(missing.is_missing(ne.soid, old_version));
+ }
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_TRUE(missing.is_missing(ne.soid));
+ EXPECT_EQ(1U, log.log.size());
+ EXPECT_EQ(0U, ondisklog.length());
+ }
+ }
+
+ // the new entry (from the logs) has a version that is lower than
+ // the old entry (from the log entry given in argument) and
+ // old is update and new is DELETE :
+ // if the object is in missing, it is removed
+ {
+ clear();
+
+ ObjectStore::Transaction t;
+ pg_log_entry_t oe;
+ pg_info_t info;
+ list<hobject_t> remove_snap;
+ bool dirty_log = false;
+
+ pg_log_entry_t ne;
+ ne.version = eversion_t(1,1);
+ ne.op = pg_log_entry_t::DELETE;
+ log.add(ne);
+
+ oe.version = eversion_t(2,1);
+ oe.op = pg_log_entry_t::MODIFY;
+ missing.add_next_event(oe);
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_TRUE(missing.is_missing(oe.soid));
+ EXPECT_EQ(1U, log.log.size());
+ EXPECT_EQ(0U, ondisklog.length());
+
+ EXPECT_FALSE(merge_old_entry(t, oe, info, remove_snap, dirty_log));
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_EQ(1U, log.log.size());
+ EXPECT_EQ(0U, ondisklog.length());
+ }
+
+ // there is no new entry (from the logs) and
+ // the old entry (from the log entry given in argument) is not a CLONE and
+ // the old entry prior_version is greater than the tail of the log :
+ // do nothing and return false
+ {
+ clear();
+
+ ObjectStore::Transaction t;
+ pg_log_entry_t oe;
+ pg_info_t info;
+ list<hobject_t> remove_snap;
+ bool dirty_log = false;
+
+ info.log_tail = eversion_t(1,1);
+ oe.op = pg_log_entry_t::MODIFY;
+ oe.prior_version = eversion_t(2,1);
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_TRUE(log.empty());
+ EXPECT_EQ(0U, ondisklog.length());
+
+ EXPECT_FALSE(merge_old_entry(t, oe, info, remove_snap, dirty_log));
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_TRUE(log.empty());
+ EXPECT_EQ(0U, ondisklog.length());
+ }
+
+ // there is no new entry (from the logs) and
+ // the old entry (from the log entry given in argument) is not a CLONE and
+ // the old entry (from the log entry given in argument) is not a DELETE and
+ // the old entry prior_version is lower than the tail of the log :
+ // add the old object to the remove_snap list and
+ // add the old object to ondisklog divergent priors and
+ // set dirty_log to true and
+ // add or update the prior_version of the object to missing and
+ // return false
+ {
+ clear();
+
+ ObjectStore::Transaction t;
+ pg_log_entry_t oe;
+ pg_info_t info;
+ list<hobject_t> remove_snap;
+ bool dirty_log = false;
+
+ info.log_tail = eversion_t(2,1);
+ oe.soid.hash = 1;
+ oe.op = pg_log_entry_t::MODIFY;
+ oe.prior_version = eversion_t(1,1);
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_TRUE(log.empty());
+ EXPECT_EQ(0U, ondisklog.length());
+
+ EXPECT_FALSE(merge_old_entry(t, oe, info, remove_snap, dirty_log));
+
+ EXPECT_TRUE(dirty_log);
+ EXPECT_EQ(oe.soid, remove_snap.front());
+ EXPECT_TRUE(t.empty());
+ EXPECT_TRUE(missing.is_missing(oe.soid));
+ EXPECT_TRUE(log.empty());
+ EXPECT_EQ(oe.soid, ondisklog.divergent_priors[oe.prior_version]);
+ }
+
+ // there is no new entry (from the logs) and
+ // the old entry (from the log entry given in argument) is not a CLONE and
+ // the old entry (from the log entry given in argument) is a DELETE and
+ // the old entry prior_version is lower than the tail of the log :
+ // add the old object to ondisklog divergent priors and
+ // set dirty_log to true and
+ // add or update the prior_version of the object to missing and
+ // return false
+ {
+ clear();
+
+ ObjectStore::Transaction t;
+ pg_log_entry_t oe;
+ pg_info_t info;
+ list<hobject_t> remove_snap;
+ bool dirty_log = false;
+
+ info.log_tail = eversion_t(2,1);
+ oe.soid.hash = 1;
+ oe.op = pg_log_entry_t::DELETE;
+ oe.prior_version = eversion_t(1,1);
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_TRUE(log.empty());
+ EXPECT_EQ(0U, ondisklog.length());
+
+ EXPECT_FALSE(merge_old_entry(t, oe, info, remove_snap, dirty_log));
+
+ EXPECT_TRUE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_TRUE(missing.is_missing(oe.soid));
+ EXPECT_TRUE(log.empty());
+ EXPECT_EQ(oe.soid, ondisklog.divergent_priors[oe.prior_version]);
+ }
+
+ // there is no new entry (from the logs) and
+ // the old entry (from the log entry given in argument) is not a CLONE and
+ // the old entry (from the log entry given in argument) is a DELETE and
+ // the old entry prior_version is eversion_t() :
+ // remove the prior_version of the object from missing, if any and
+ // return false
+ {
+ clear();
+
+ ObjectStore::Transaction t;
+ pg_log_entry_t oe;
+ pg_info_t info;
+ list<hobject_t> remove_snap;
+ bool dirty_log = false;
+
+ info.log_tail = eversion_t(10,1);
+ oe.soid.hash = 1;
+ oe.op = pg_log_entry_t::DELETE;
+ oe.prior_version = eversion_t();
+
+ missing.add(oe.soid, eversion_t(1,1), eversion_t());
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_TRUE(missing.is_missing(oe.soid));
+ EXPECT_TRUE(log.empty());
+ EXPECT_EQ(0U, ondisklog.length());
+
+ EXPECT_FALSE(merge_old_entry(t, oe, info, remove_snap, dirty_log));
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_TRUE(log.empty());
+ EXPECT_EQ(0U, ondisklog.length());
+ }
+
+ // there is no new entry (from the logs) and
+ // the old entry (from the log entry given in argument) is not a CLONE and
+ // the old entry (from the log entry given in argument) is not a DELETE and
+ // the old entry prior_version is eversion_t() :
+ // add the old object to the remove_snap list and
+ // remove the prior_version of the object from missing, if any and
+ // return false
+ {
+ clear();
+
+ ObjectStore::Transaction t;
+ pg_log_entry_t oe;
+ pg_info_t info;
+ list<hobject_t> remove_snap;
+ bool dirty_log = false;
+
+ info.log_tail = eversion_t(10,1);
+ oe.soid.hash = 1;
+ oe.op = pg_log_entry_t::MODIFY;
+ oe.prior_version = eversion_t();
+
+ missing.add(oe.soid, eversion_t(1,1), eversion_t());
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_TRUE(remove_snap.empty());
+ EXPECT_TRUE(t.empty());
+ EXPECT_TRUE(missing.is_missing(oe.soid));
+ EXPECT_TRUE(log.empty());
+ EXPECT_EQ(0U, ondisklog.length());
+
+ EXPECT_FALSE(merge_old_entry(t, oe, info, remove_snap, dirty_log));
+
+ EXPECT_FALSE(dirty_log);
+ EXPECT_EQ(oe.soid, remove_snap.front());
+ EXPECT_TRUE(t.empty());
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_TRUE(log.empty());
+ EXPECT_EQ(0U, ondisklog.length());
+ }
+
+}
+
+int main(int argc, char **argv) {
+ vector<const char*> args;
+ argv_to_vec(argc, (const char **)argv, args);
+
+ global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+ common_init_finish(g_ceph_context);
+
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+
+// Local Variables:
+// compile-command: "cd ../.. ; make unittest_pglog ; ./unittest_pglog --log-to-stderr=true --debug-osd=20 # --gtest_filter=*.* "
+// End: