summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoic Dachary <loic@dachary.org>2013-05-28 23:34:59 +0200
committerLoic Dachary <loic@dachary.org>2013-05-31 19:58:52 +0200
commitddb3a8d6ae6174d57a58c59a73724975914ffd4b (patch)
tree488cbf9f1983fb7b68dcfa61debc85986f2d0d29
parentdb85c52d4cff8f541e2cdd30e7a28cadf4bf516f (diff)
downloadceph-ddb3a8d6ae6174d57a58c59a73724975914ffd4b.tar.gz
unit tests for pg_missing_t
All lines of code are tested. The conditions under which some methods could corrupt the content of a pg_missing_t object have not been investigated. Since the data members are public, the caller is ultimately responsible for the consistency of the object and the methods have no way to enforce it. The semantics of is_missing have been discussed in http://thread.gmane.org/gmane.comp.file-systems.ceph.devel/15280 Signed-off-by: Loic Dachary <loic@dachary.org>
-rw-r--r--src/test/test_osd_types.cc332
1 files changed, 319 insertions, 13 deletions
diff --git a/src/test/test_osd_types.cc b/src/test/test_osd_types.cc
index d3f5364f793..c0a9a95b11a 100644
--- a/src/test/test_osd_types.cc
+++ b/src/test/test_osd_types.cc
@@ -4,6 +4,9 @@
* Ceph - scalable distributed file system
*
* Copyright (C) 2011 New Dream Network
+ * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic@dachary.org>
*
* This is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
@@ -224,25 +227,328 @@ TEST(pg_missing_t, constructor)
EXPECT_FALSE(missing.have_missing());
}
-TEST(pg_missing_t, add_next_event)
+TEST(pg_missing_t, have_missing)
{
- pg_missing_t missing;
-
- // adding a DELETE entry
hobject_t oid(object_t("objname"), "key", 123, 456, 0);
- eversion_t version(1,2);
- eversion_t prior_version(3,4);
- pg_log_entry_t e(pg_log_entry_t::DELETE, oid, version, prior_version,
- osd_reqid_t(entity_name_t::CLIENT(777), 8, 999), utime_t(8,9));
- EXPECT_FALSE(missing.have_missing());
- missing.add_next_event(e);
+ pg_missing_t missing;
EXPECT_FALSE(missing.have_missing());
+ missing.add(oid, eversion_t(), eversion_t());
+ EXPECT_TRUE(missing.have_missing());
+}
- // adding a MODIFY entry
- e.op = pg_log_entry_t::MODIFY;
+TEST(pg_missing_t, swap)
+{
+ hobject_t oid(object_t("objname"), "key", 123, 456, 0);
+ pg_missing_t missing;
EXPECT_FALSE(missing.have_missing());
- missing.add_next_event(e);
+ missing.add(oid, eversion_t(), eversion_t());
EXPECT_TRUE(missing.have_missing());
+
+ pg_missing_t other;
+ EXPECT_FALSE(other.have_missing());
+
+ other.swap(missing);
+ EXPECT_FALSE(missing.have_missing());
+ EXPECT_TRUE(other.have_missing());
+}
+
+TEST(pg_missing_t, is_missing)
+{
+ // pg_missing_t::is_missing(const hobject_t& oid) const
+ {
+ hobject_t oid(object_t("objname"), "key", 123, 456, 0);
+ pg_missing_t missing;
+ EXPECT_FALSE(missing.is_missing(oid));
+ missing.add(oid, eversion_t(), eversion_t());
+ EXPECT_TRUE(missing.is_missing(oid));
+ }
+
+ // bool pg_missing_t::is_missing(const hobject_t& oid, eversion_t v) const
+ {
+ hobject_t oid(object_t("objname"), "key", 123, 456, 0);
+ pg_missing_t missing;
+ eversion_t need(10,5);
+ EXPECT_FALSE(missing.is_missing(oid, eversion_t()));
+ missing.add(oid, need, eversion_t());
+ EXPECT_TRUE(missing.is_missing(oid));
+ EXPECT_FALSE(missing.is_missing(oid, eversion_t()));
+ EXPECT_TRUE(missing.is_missing(oid, need));
+ }
+}
+
+TEST(pg_missing_t, have_old)
+{
+ hobject_t oid(object_t("objname"), "key", 123, 456, 0);
+ pg_missing_t missing;
+ EXPECT_EQ(eversion_t(), missing.have_old(oid));
+ missing.add(oid, eversion_t(), eversion_t());
+ EXPECT_EQ(eversion_t(), missing.have_old(oid));
+ eversion_t have(1,1);
+ missing.revise_have(oid, have);
+ EXPECT_EQ(have, missing.have_old(oid));
+}
+
+TEST(pg_missing_t, add_next_event)
+{
+ hobject_t oid(object_t("objname"), "key", 123, 456, 0);
+ hobject_t oid_other(object_t("other"), "key", 9123, 9456, 0);
+ eversion_t version(10,5);
+ eversion_t prior_version(3,4);
+ pg_log_entry_t sample_e(pg_log_entry_t::DELETE, oid, version, prior_version,
+ osd_reqid_t(entity_name_t::CLIENT(777), 8, 999), utime_t(8,9));
+
+ // new object (MODIFY)
+ {
+ pg_missing_t missing;
+ pg_log_entry_t e = sample_e;
+
+ e.op = pg_log_entry_t::MODIFY;
+ e.prior_version = eversion_t();
+ EXPECT_TRUE(e.is_update());
+ EXPECT_FALSE(missing.is_missing(oid));
+ missing.add_next_event(e);
+ EXPECT_TRUE(missing.is_missing(oid));
+ EXPECT_EQ(eversion_t(), missing.missing[oid].have);
+ EXPECT_EQ(oid, missing.rmissing[e.version.version]);
+ EXPECT_EQ(1U, missing.num_missing());
+ EXPECT_EQ(1U, missing.rmissing.size());
+
+ // adding the same object replaces the previous one
+ missing.add_next_event(e);
+ EXPECT_TRUE(missing.is_missing(oid));
+ EXPECT_EQ(1U, missing.num_missing());
+ EXPECT_EQ(1U, missing.rmissing.size());
+ }
+
+ // new object (CLONE)
+ {
+ pg_missing_t missing;
+ pg_log_entry_t e = sample_e;
+
+ e.op = pg_log_entry_t::CLONE;
+ e.prior_version = eversion_t();
+ EXPECT_TRUE(e.is_clone());
+ EXPECT_FALSE(missing.is_missing(oid));
+ missing.add_next_event(e);
+ EXPECT_TRUE(missing.is_missing(oid));
+ EXPECT_EQ(eversion_t(), missing.missing[oid].have);
+ EXPECT_EQ(oid, missing.rmissing[e.version.version]);
+ EXPECT_EQ(1U, missing.num_missing());
+ EXPECT_EQ(1U, missing.rmissing.size());
+
+ // adding the same object replaces the previous one
+ missing.add_next_event(e);
+ EXPECT_TRUE(missing.is_missing(oid));
+ EXPECT_EQ(1U, missing.num_missing());
+ EXPECT_EQ(1U, missing.rmissing.size());
+ }
+
+ // existing object (MODIFY)
+ {
+ pg_missing_t missing;
+ pg_log_entry_t e = sample_e;
+
+ e.op = pg_log_entry_t::MODIFY;
+ e.prior_version = eversion_t();
+ EXPECT_TRUE(e.is_update());
+ EXPECT_FALSE(missing.is_missing(oid));
+ missing.add_next_event(e);
+ EXPECT_TRUE(missing.is_missing(oid));
+ EXPECT_EQ(eversion_t(), missing.missing[oid].have);
+ EXPECT_EQ(oid, missing.rmissing[e.version.version]);
+ EXPECT_EQ(1U, missing.num_missing());
+ EXPECT_EQ(1U, missing.rmissing.size());
+
+ // adding the same object with a different version
+ e.prior_version = prior_version;
+ missing.add_next_event(e);
+ EXPECT_EQ(eversion_t(), missing.missing[oid].have);
+ EXPECT_TRUE(missing.is_missing(oid));
+ EXPECT_EQ(1U, missing.num_missing());
+ EXPECT_EQ(1U, missing.rmissing.size());
+ }
+
+ // object with prior version (MODIFY)
+ {
+ pg_missing_t missing;
+ pg_log_entry_t e = sample_e;
+
+ e.op = pg_log_entry_t::MODIFY;
+ EXPECT_TRUE(e.is_update());
+ EXPECT_FALSE(missing.is_missing(oid));
+ missing.add_next_event(e);
+ EXPECT_TRUE(missing.is_missing(oid));
+ EXPECT_EQ(prior_version, missing.missing[oid].have);
+ EXPECT_EQ(version, missing.missing[oid].need);
+ EXPECT_EQ(oid, missing.rmissing[e.version.version]);
+ EXPECT_EQ(1U, missing.num_missing());
+ EXPECT_EQ(1U, missing.rmissing.size());
+ }
+
+ // obsolete (BACKLOG)
+ {
+ pg_missing_t missing;
+ pg_log_entry_t e = sample_e;
+
+ e.op = pg_log_entry_t::BACKLOG;
+ EXPECT_TRUE(e.is_backlog());
+ EXPECT_FALSE(missing.is_missing(oid));
+ EXPECT_THROW(missing.add_next_event(e), FailedAssertion);
+ }
+
+ // adding a DELETE matching an existing event
+ {
+ pg_missing_t missing;
+ pg_log_entry_t e = sample_e;
+
+ e.op = pg_log_entry_t::MODIFY;
+ EXPECT_TRUE(e.is_update());
+ EXPECT_FALSE(missing.is_missing(oid));
+ missing.add_next_event(e);
+ EXPECT_TRUE(missing.is_missing(oid));
+
+ e.op = pg_log_entry_t::DELETE;
+ EXPECT_TRUE(e.is_delete());
+ missing.add_next_event(e);
+ EXPECT_FALSE(missing.have_missing());
+ }
+}
+
+TEST(pg_missing_t, revise_need)
+{
+ hobject_t oid(object_t("objname"), "key", 123, 456, 0);
+ pg_missing_t missing;
+ // create a new entry
+ EXPECT_FALSE(missing.is_missing(oid));
+ eversion_t need(10,10);
+ missing.revise_need(oid, need);
+ EXPECT_TRUE(missing.is_missing(oid));
+ EXPECT_EQ(eversion_t(), missing.missing[oid].have);
+ EXPECT_EQ(need, missing.missing[oid].need);
+ // update an existing entry and preserve have
+ eversion_t have(1,1);
+ missing.revise_have(oid, have);
+ eversion_t new_need(10,12);
+ EXPECT_EQ(have, missing.missing[oid].have);
+ missing.revise_need(oid, new_need);
+ EXPECT_EQ(have, missing.missing[oid].have);
+ EXPECT_EQ(new_need, missing.missing[oid].need);
+}
+
+TEST(pg_missing_t, revise_have)
+{
+ hobject_t oid(object_t("objname"), "key", 123, 456, 0);
+ pg_missing_t missing;
+ // a non existing entry means noop
+ EXPECT_FALSE(missing.is_missing(oid));
+ eversion_t have(1,1);
+ missing.revise_have(oid, have);
+ EXPECT_FALSE(missing.is_missing(oid));
+ // update an existing entry
+ eversion_t need(10,12);
+ missing.add(oid, need, have);
+ EXPECT_TRUE(missing.is_missing(oid));
+ eversion_t new_have(2,2);
+ EXPECT_EQ(have, missing.missing[oid].have);
+ missing.revise_have(oid, new_have);
+ EXPECT_EQ(new_have, missing.missing[oid].have);
+ EXPECT_EQ(need, missing.missing[oid].need);
+}
+
+TEST(pg_missing_t, add)
+{
+ hobject_t oid(object_t("objname"), "key", 123, 456, 0);
+ pg_missing_t missing;
+ EXPECT_FALSE(missing.is_missing(oid));
+ eversion_t have(1,1);
+ eversion_t need(10,10);
+ missing.add(oid, need, have);
+ EXPECT_TRUE(missing.is_missing(oid));
+ EXPECT_EQ(have, missing.missing[oid].have);
+ EXPECT_EQ(need, missing.missing[oid].need);
+}
+
+TEST(pg_missing_t, rm)
+{
+ // void pg_missing_t::rm(const hobject_t& oid, eversion_t v)
+ {
+ hobject_t oid(object_t("objname"), "key", 123, 456, 0);
+ pg_missing_t missing;
+ EXPECT_FALSE(missing.is_missing(oid));
+ epoch_t epoch = 10;
+ eversion_t need(epoch,10);
+ missing.add(oid, need, eversion_t());
+ EXPECT_TRUE(missing.is_missing(oid));
+ // rm of an older version is a noop
+ missing.rm(oid, eversion_t(epoch / 2,20));
+ EXPECT_TRUE(missing.is_missing(oid));
+ // rm of a later version removes the object
+ missing.rm(oid, eversion_t(epoch * 2,20));
+ EXPECT_FALSE(missing.is_missing(oid));
+ }
+ // void pg_missing_t::rm(const std::map<hobject_t, pg_missing_t::item>::iterator &m)
+ {
+ hobject_t oid(object_t("objname"), "key", 123, 456, 0);
+ pg_missing_t missing;
+ EXPECT_FALSE(missing.is_missing(oid));
+ missing.add(oid, eversion_t(), eversion_t());
+ EXPECT_TRUE(missing.is_missing(oid));
+ const std::map<hobject_t, pg_missing_t::item>::iterator m = missing.missing.find(oid);
+ missing.rm(m);
+ EXPECT_FALSE(missing.is_missing(oid));
+ }
+}
+
+TEST(pg_missing_t, got)
+{
+ // void pg_missing_t::got(const hobject_t& oid, eversion_t v)
+ {
+ hobject_t oid(object_t("objname"), "key", 123, 456, 0);
+ pg_missing_t missing;
+ // assert if the oid does not exist
+ EXPECT_THROW(missing.got(oid, eversion_t()), FailedAssertion);
+ EXPECT_FALSE(missing.is_missing(oid));
+ epoch_t epoch = 10;
+ eversion_t need(epoch,10);
+ missing.add(oid, need, eversion_t());
+ EXPECT_TRUE(missing.is_missing(oid));
+ // assert if that the version to be removed is lower than the version of the object
+ EXPECT_THROW(missing.got(oid, eversion_t(epoch / 2,20)), FailedAssertion);
+ // remove of a later version removes the object
+ missing.got(oid, eversion_t(epoch * 2,20));
+ EXPECT_FALSE(missing.is_missing(oid));
+ }
+ // void pg_missing_t::got(const std::map<hobject_t, pg_missing_t::item>::iterator &m)
+ {
+ hobject_t oid(object_t("objname"), "key", 123, 456, 0);
+ pg_missing_t missing;
+ EXPECT_FALSE(missing.is_missing(oid));
+ missing.add(oid, eversion_t(), eversion_t());
+ EXPECT_TRUE(missing.is_missing(oid));
+ const std::map<hobject_t, pg_missing_t::item>::iterator m = missing.missing.find(oid);
+ missing.got(m);
+ EXPECT_FALSE(missing.is_missing(oid));
+ }
+}
+
+TEST(pg_missing_t, split_into)
+{
+ uint32_t hash1 = 1;
+ hobject_t oid1(object_t("objname"), "key1", 123, hash1, 0);
+ uint32_t hash2 = 2;
+ hobject_t oid2(object_t("objname"), "key2", 123, hash2, 0);
+ pg_missing_t missing;
+ missing.add(oid1, eversion_t(), eversion_t());
+ missing.add(oid2, eversion_t(), eversion_t());
+ pg_t child_pgid;
+ child_pgid.m_seed = 1;
+ pg_missing_t child;
+ unsigned split_bits = 1;
+ missing.split_into(child_pgid, split_bits, &child);
+ EXPECT_TRUE(child.is_missing(oid1));
+ EXPECT_FALSE(child.is_missing(oid2));
+ EXPECT_FALSE(missing.is_missing(oid1));
+ EXPECT_TRUE(missing.is_missing(oid2));
}
// Local Variables: