*/
#include "stats_test.h"
+#include "evp_store_single_threaded_test.h"
+#include "test_helpers.h"
#include <gmock/gmock.h>
return stats;
}
+class DatatypeStatTest : public StatTest,
+ public ::testing::WithParamInterface<std::string> {
+protected:
+ void SetUp() override {
+ config_string += std::string{"item_eviction_policy="} + GetParam();
+ StatTest::SetUp();
+ }
+};
+
TEST_F(StatTest, vbucket_seqno_stats_test) {
using namespace testing;
const std::string vbucket = "vb_" + std::to_string(vbid);
Pair(vbucket + ":last_persisted_snap_start", "0"),
Pair(vbucket + ":last_persisted_snap_end", "0")));
}
+
+TEST_P(DatatypeStatTest, datatypesInitiallyZero) {
+ // Check that the datatype stats initialise to 0
+ auto vals = get_stat(nullptr);
+ EXPECT_EQ(0, std::stoi(vals["ep_active_datatype_snappy"]));
+ EXPECT_EQ(0, std::stoi(vals["ep_active_datatype_snappy,json"]));
+ EXPECT_EQ(0, std::stoi(vals["ep_active_datatype_snappy,xattr"]));
+ EXPECT_EQ(0, std::stoi(vals["ep_active_datatype_json"]));
+ EXPECT_EQ(0, std::stoi(vals["ep_active_datatype_json,xattr"]));
+ EXPECT_EQ(0, std::stoi(vals["ep_active_datatype_raw"]));
+ EXPECT_EQ(0, std::stoi(vals["ep_active_datatype_xattr"]));
+ EXPECT_EQ(0, std::stoi(vals["ep_active_datatype_snappy,json,xattr"]));
+
+ EXPECT_EQ(0, std::stoi(vals["ep_replica_datatype_snappy"]));
+ EXPECT_EQ(0, std::stoi(vals["ep_replica_datatype_snappy,json"]));
+ EXPECT_EQ(0, std::stoi(vals["ep_replica_datatype_snappy,xattr"]));
+ EXPECT_EQ(0, std::stoi(vals["ep_replica_datatype_json"]));
+ EXPECT_EQ(0, std::stoi(vals["ep_replica_datatype_json,xattr"]));
+ EXPECT_EQ(0, std::stoi(vals["ep_replica_datatype_raw"]));
+ EXPECT_EQ(0, std::stoi(vals["ep_replica_datatype_xattr"]));
+ EXPECT_EQ(0, std::stoi(vals["ep_replica_datatype_snappy,json,xattr"]));
+}
+
+void setDatatypeItem(KVBucket* store,
+ const void* cookie,
+ protocol_binary_datatype_t datatype,
+ std::string name, std::string val = "[0]") {
+ Item item(make_item(
+ 0, {name, DocNamespace::DefaultCollection}, val, 0, datatype));
+ store->set(item, cookie);
+}
+
+TEST_P(DatatypeStatTest, datatypeJsonToXattr) {
+ setDatatypeItem(store, cookie, PROTOCOL_BINARY_DATATYPE_JSON, "jsonDoc");
+ auto vals = get_stat(nullptr);
+ EXPECT_EQ(1, std::stoi(vals["ep_active_datatype_json"]));
+
+ // Check that updating an items datatype works
+ setDatatypeItem(store, cookie, PROTOCOL_BINARY_DATATYPE_XATTR, "jsonDoc");
+ vals = get_stat(nullptr);
+
+ EXPECT_EQ(1, std::stoi(vals["ep_active_datatype_xattr"]));
+ EXPECT_EQ(0, std::stoi(vals["ep_active_datatype_json"]));
+}
+
+TEST_P(DatatypeStatTest, datatypeRawStatTest) {
+ setDatatypeItem(store, cookie, 0, "rawDoc");
+ auto vals = get_stat(nullptr);
+ EXPECT_EQ(1, std::stoi(vals["ep_active_datatype_raw"]));
+}
+
+TEST_P(DatatypeStatTest, datatypeXattrStatTest) {
+ setDatatypeItem(store, cookie, PROTOCOL_BINARY_DATATYPE_XATTR, "xattrDoc");
+ auto vals = get_stat(nullptr);
+ EXPECT_EQ(1, std::stoi(vals["ep_active_datatype_xattr"]));
+ // Update the same key with a different value. The datatype stat should
+ // stay the same
+ setDatatypeItem(store, cookie, PROTOCOL_BINARY_DATATYPE_XATTR,
+ "xattrDoc", "[2]");
+ vals = get_stat(nullptr);
+ EXPECT_EQ(1, std::stoi(vals["ep_active_datatype_xattr"]));
+}
+
+TEST_P(DatatypeStatTest, datatypeCompressedStatTest) {
+ setDatatypeItem(store,
+ cookie,
+ PROTOCOL_BINARY_DATATYPE_SNAPPY,
+ "compressedDoc");
+ auto vals = get_stat(nullptr);
+ EXPECT_EQ(1, std::stoi(vals["ep_active_datatype_snappy"]));
+}
+
+TEST_P(DatatypeStatTest, datatypeCompressedJson) {
+ setDatatypeItem(
+ store,
+ cookie,
+ PROTOCOL_BINARY_DATATYPE_JSON | PROTOCOL_BINARY_DATATYPE_SNAPPY,
+ "jsonCompressedDoc");
+ auto vals = get_stat(nullptr);
+ EXPECT_EQ(1, std::stoi(vals["ep_active_datatype_snappy,json"]));
+}
+
+TEST_P(DatatypeStatTest, datatypeCompressedXattr) {
+ setDatatypeItem(store,
+ cookie,
+ PROTOCOL_BINARY_DATATYPE_XATTR |
+ PROTOCOL_BINARY_DATATYPE_SNAPPY,
+ "xattrCompressedDoc");
+ auto vals = get_stat(nullptr);
+ EXPECT_EQ(1, std::stoi(vals["ep_active_datatype_snappy,xattr"]));
+}
+
+TEST_P(DatatypeStatTest, datatypeJsonXattr) {
+ setDatatypeItem(
+ store,
+ cookie,
+ PROTOCOL_BINARY_DATATYPE_JSON | PROTOCOL_BINARY_DATATYPE_XATTR,
+ "jsonXattrDoc");
+ auto vals = get_stat(nullptr);
+ EXPECT_EQ(1, std::stoi(vals["ep_active_datatype_json,xattr"]));
+}
+
+TEST_P(DatatypeStatTest, datatypeDeletion) {
+ setDatatypeItem(
+ store,
+ cookie,
+ PROTOCOL_BINARY_DATATYPE_JSON | PROTOCOL_BINARY_DATATYPE_XATTR,
+ "jsonXattrDoc");
+ auto vals = get_stat(nullptr);
+ EXPECT_EQ(1, std::stoi(vals["ep_active_datatype_json,xattr"]));
+ uint64_t cas = 0;
+ store->deleteItem({"jsonXattrDoc", DocNamespace::DefaultCollection},
+ cas,
+ 0,
+ cookie,
+ nullptr,
+ nullptr,
+ nullptr);
+ vals = get_stat(nullptr);
+ EXPECT_EQ(0, std::stoi(vals["ep_active_datatype_json,xattr"]));
+}
+
+TEST_P(DatatypeStatTest, datatypeCompressedJsonXattr) {
+ setDatatypeItem(store,
+ cookie,
+ PROTOCOL_BINARY_DATATYPE_JSON |
+ PROTOCOL_BINARY_DATATYPE_SNAPPY |
+ PROTOCOL_BINARY_DATATYPE_XATTR,
+ "jsonCompressedXattrDoc");
+ auto vals = get_stat(nullptr);
+ EXPECT_EQ(1, std::stoi(vals["ep_active_datatype_snappy,json,xattr"]));
+}
+
+TEST_P(DatatypeStatTest, datatypeExpireItem) {
+ Item item(make_item(
+ 0, {"expiryDoc", DocNamespace::DefaultCollection}, "[0]", 1,
+ PROTOCOL_BINARY_DATATYPE_JSON));
+ store->set(item, cookie);
+ store->get({"expiryDoc", DocNamespace::DefaultCollection}, 0, cookie, NONE);
+ auto vals = get_stat(nullptr);
+
+ //Should be 0, becuase the doc should have expired
+ EXPECT_EQ(0, std::stoi(vals["ep_active_datatype_json"]));
+}
+
+
+TEST_P(DatatypeStatTest, datatypeEviction) {
+ const DocKey key = {"jsonXattrDoc", DocNamespace::DefaultCollection};
+ setDatatypeItem(
+ store,
+ cookie,
+ PROTOCOL_BINARY_DATATYPE_JSON | PROTOCOL_BINARY_DATATYPE_XATTR,
+ "jsonXattrDoc");
+ auto vals = get_stat(nullptr);
+ EXPECT_EQ(1, std::stoi(vals["ep_active_datatype_json,xattr"]));
+ store->flushVBucket(0);
+ const char* msg;
+ store->evictKey(key, 0, &msg);
+ vals = get_stat(nullptr);
+ if (GetParam() == "value_only"){
+ // Should still be 1 as only value is evicted
+ EXPECT_EQ(1, std::stoi(vals["ep_active_datatype_json,xattr"]));
+ } else {
+ // Should be 0 as everything is evicted
+ EXPECT_EQ(0, std::stoi(vals["ep_active_datatype_json,xattr"]));
+ }
+
+ store->get(key, 0, cookie, QUEUE_BG_FETCH);
+ if (GetParam() == "full_eviction") {
+ // Run the bgfetch to restore the item from disk
+ ExTask task = new SingleBGFetcherTask(
+ engine.get(), key, 0, cookie, false, 0, false);
+ task_executor->schedule(task);
+ runNextTask(*task_executor->getLpTaskQ()[READER_TASK_IDX]);
+ }
+ vals = get_stat(nullptr);
+ // The item should be restored to memory, hence added back to the stats
+ EXPECT_EQ(1, std::stoi(vals["ep_active_datatype_json,xattr"]));
+}
+
+TEST_P(DatatypeStatTest, MB23892) {
+ // This test checks that updating a document with a different datatype is
+ // safe to do after an eviction (where the blob is now null)
+ const DocKey key = {"jsonXattrDoc", DocNamespace::DefaultCollection};
+ setDatatypeItem(
+ store,
+ cookie,
+ PROTOCOL_BINARY_DATATYPE_JSON | PROTOCOL_BINARY_DATATYPE_XATTR,
+ "jsonXattrDoc");
+ auto vals = get_stat(nullptr);
+ EXPECT_EQ(1, std::stoi(vals["ep_active_datatype_json,xattr"]));
+ store->flushVBucket(0);
+ const char* msg;
+ store->evictKey(key, 0, &msg);
+ store->flushVBucket(0);
+ setDatatypeItem(store, cookie, PROTOCOL_BINARY_DATATYPE_JSON, "jsonXattrDoc", "[1]");
+}
+
+INSTANTIATE_TEST_CASE_P(FullAndValueEviction, DatatypeStatTest,
+ ::testing::Values("value_only", "full_eviction"), []
+ (const ::testing::TestParamInfo<std::string>&
+ info) {return info.param;});