19e197a92SJim Walker /*
275d47588SCouchbase Build Team  *     Copyright 2017-Present Couchbase, Inc.
39e197a92SJim Walker  *
475d47588SCouchbase Build Team  *   Use of this software is governed by the Business Source License included
575d47588SCouchbase Build Team  *   in the file licenses/BSL-Couchbase.txt.  As of the Change Date specified
675d47588SCouchbase Build Team  *   in that file, in accordance with the Business Source License, use of this
775d47588SCouchbase Build Team  *   software will be governed by the Apache License, Version 2.0, included in
875d47588SCouchbase Build Team  *   the file licenses/APL2.txt.
99e197a92SJim Walker  */
109e197a92SJim Walker 
119e197a92SJim Walker #include "testapp.h"
129e197a92SJim Walker #include "testapp_client_test.h"
139e197a92SJim Walker 
145597a9abSTrond Norbye #include <protocol/connection/client_mcbp_commands.h>
159e197a92SJim Walker #include <xattr/blob.h>
169e197a92SJim Walker #include <xattr/utils.h>
179e197a92SJim Walker 
1886724888SJim Walker class WithMetaTest : public TestappXattrClientTest {
199e197a92SJim Walker public:
2086724888SJim Walker     void SetUp() override {
2186724888SJim Walker         TestappXattrClientTest::SetUp();
2286724888SJim Walker         document.info.cas = testCas; // Must have a cas for meta ops
239e197a92SJim Walker     }
249e197a92SJim Walker 
259e197a92SJim Walker     /**
269e197a92SJim Walker      * Check the CAS of the set document against our value
279e197a92SJim Walker      * using vattr for the lookup
289e197a92SJim Walker      */
299e197a92SJim Walker     void checkCas() {
309e197a92SJim Walker         BinprotSubdocCommand cmd;
31a531b0faSTrond Norbye         cmd.setOp(cb::mcbp::ClientOpcode::SubdocGet);
329e197a92SJim Walker         cmd.setKey(name);
339e197a92SJim Walker         cmd.setPath("$document");
349e197a92SJim Walker         cmd.addPathFlags(SUBDOC_FLAG_XATTR_PATH);
358bfdba48STrond Norbye         cmd.addDocFlags(cb::mcbp::subdoc::doc_flag::None);
369e197a92SJim Walker 
37cc0ee8fdSTrond Norbye         auto resp = userConnection->execute(cmd);
389e197a92SJim Walker 
3945cbd889STrond Norbye         ASSERT_EQ(cb::mcbp::Status::Success, resp.getStatus());
4046c1dcbfSTrond Norbye         auto json = nlohmann::json::parse(resp.getDataString());
4146c1dcbfSTrond Norbye         EXPECT_STREQ(testCasStr, json["CAS"].get<std::string>().c_str());
429e197a92SJim Walker     }
439e197a92SJim Walker 
449e197a92SJim Walker     /**
459e197a92SJim Walker      * Make ::document an xattr value
469e197a92SJim Walker      */
479e197a92SJim Walker     void makeDocumentXattrValue() {
489e197a92SJim Walker         cb::xattr::Blob blob;
497537e2faSRichard de Mellow         blob.set("user", R"({"author":"bubba"})");
507537e2faSRichard de Mellow         blob.set("meta", R"({"content-type":"text"})");
519e197a92SJim Walker 
529e197a92SJim Walker         auto xattrValue = blob.finalize();
539e197a92SJim Walker 
549e197a92SJim Walker         // append body to the xattrs and store in data
559e197a92SJim Walker         std::string body = "document_body";
56029c09a5SDave Rigby         document.value = xattrValue;
57029c09a5SDave Rigby         document.value += body;
589e197a92SJim Walker         document.info.datatype = cb::mcbp::Datatype::Xattr;
5929b49918SDave Rigby 
6029b49918SDave Rigby         if (hasSnappySupport() == ClientSnappySupport::Yes) {
6129b49918SDave Rigby             document.compress();
6229b49918SDave Rigby         }
639e197a92SJim Walker     }
649e197a92SJim Walker 
659e197a92SJim Walker protected:
66233ea88eSPaolo Cocchi     /**
67233ea88eSPaolo Cocchi      * Test that DelWithMeta accepts user-xattrs in the payload.
68233ea88eSPaolo Cocchi      *
69233ea88eSPaolo Cocchi      * @param allowValuePruning Whether the engine sanitizes bad user payloads
70233ea88eSPaolo Cocchi      *  or fails the request
71b08424f8SPaolo Cocchi      * @param compressed Whether the payload is compressed
72233ea88eSPaolo Cocchi      */
73b08424f8SPaolo Cocchi     void testDeleteWithMetaAcceptsUserXattrs(bool allowValuePruning,
74b08424f8SPaolo Cocchi                                              bool compressed = false);
75233ea88eSPaolo Cocchi 
76233ea88eSPaolo Cocchi     /**
77233ea88eSPaolo Cocchi      * Test that DelWithMeta rejects body in the payload.
78233ea88eSPaolo Cocchi      *
79233ea88eSPaolo Cocchi      * @param allowValuePruning Whether the engine sanitizes bad user payloads
80233ea88eSPaolo Cocchi      *  or fails the request
81233ea88eSPaolo Cocchi      * @param dtXattr Whether the value under test is DT Xattr
82233ea88eSPaolo Cocchi      */
83233ea88eSPaolo Cocchi     void testDeleteWithMetaRejectsBody(bool allowValuePruning, bool dtXattr);
84233ea88eSPaolo Cocchi 
859e197a92SJim Walker     const uint64_t testCas = 0xb33ff00dcafef00dull;
869e197a92SJim Walker     const char* testCasStr = "0xb33ff00dcafef00d";
879e197a92SJim Walker };
889e197a92SJim Walker 
890cff52a7SDave Rigby INSTANTIATE_TEST_SUITE_P(
9086724888SJim Walker         TransportProtocols,
919e197a92SJim Walker         WithMetaTest,
92cce63037STrond Norbye         ::testing::Combine(::testing::Values(TransportProtocols::McbpSsl),
9386724888SJim Walker                            ::testing::Values(XattrSupport::Yes,
948b26531fSDave Rigby                                              XattrSupport::No),
958b26531fSDave Rigby                            ::testing::Values(ClientJSONSupport::Yes,
967728129dSDave Rigby                                              ClientJSONSupport::No),
9729b49918SDave Rigby                            ::testing::Values(ClientSnappySupport::Yes,
9829b49918SDave Rigby                                              ClientSnappySupport::No)),
9986724888SJim Walker         PrintToStringCombinedName());
1009e197a92SJim Walker 
1019e197a92SJim Walker TEST_P(WithMetaTest, basicSet) {
102a531b0faSTrond Norbye     TESTAPP_SKIP_IF_UNSUPPORTED(cb::mcbp::ClientOpcode::SetWithMeta);
1039e197a92SJim Walker 
10486724888SJim Walker     MutationInfo resp;
10586724888SJim Walker     try {
106cc0ee8fdSTrond Norbye         resp = userConnection->mutateWithMeta(document,
10786a6e636SChristopher Farman                                               Vbid(0),
108cf97e679STrond Norbye                                               cb::mcbp::cas::Wildcard,
10986724888SJim Walker                                               /*seqno*/ 1,
11086724888SJim Walker                                               /*options*/ 0,
11186724888SJim Walker                                               {});
112682d2e38STim Bradgate     } catch (std::exception&) {
11386724888SJim Walker         FAIL() << "mutateWithMeta threw an exception";
11486724888SJim Walker     }
11586724888SJim Walker 
11686724888SJim Walker     if (::testing::get<1>(GetParam()) == XattrSupport::Yes) {
1179e197a92SJim Walker         checkCas();
1189e197a92SJim Walker     }
11986724888SJim Walker }
1209e197a92SJim Walker 
1219e197a92SJim Walker TEST_P(WithMetaTest, basicSetXattr) {
122a531b0faSTrond Norbye     TESTAPP_SKIP_IF_UNSUPPORTED(cb::mcbp::ClientOpcode::SetWithMeta);
1239e197a92SJim Walker     makeDocumentXattrValue();
1249e197a92SJim Walker 
12586724888SJim Walker     MutationInfo resp;
12686724888SJim Walker     try {
127cc0ee8fdSTrond Norbye         resp = userConnection->mutateWithMeta(document,
12886a6e636SChristopher Farman                                               Vbid(0),
129cf97e679STrond Norbye                                               cb::mcbp::cas::Wildcard,
13086724888SJim Walker                                               /*seqno*/ 1,
13186724888SJim Walker                                               /*options*/ 0,
13286724888SJim Walker                                               {});
13386724888SJim Walker         EXPECT_EQ(XattrSupport::Yes, ::testing::get<1>(GetParam()));
134d3a578c3STrond Norbye         EXPECT_EQ(testCas, resp.cas);
135682d2e38STim Bradgate     } catch (std::exception&) {
13686724888SJim Walker         EXPECT_EQ(XattrSupport::No, ::testing::get<1>(GetParam()));
13786724888SJim Walker     }
1389e197a92SJim Walker 
13986724888SJim Walker     if (::testing::get<1>(GetParam()) == XattrSupport::Yes) {
1409e197a92SJim Walker         checkCas();
1419e197a92SJim Walker     }
14286724888SJim Walker }
143482acea6STrond Norbye 
144482acea6STrond Norbye TEST_P(WithMetaTest, MB36304_DocumetTooBig) {
145482acea6STrond Norbye     TESTAPP_SKIP_IF_UNSUPPORTED(cb::mcbp::ClientOpcode::SetWithMeta);
146482acea6STrond Norbye     if (::testing::get<3>(GetParam()) == ClientSnappySupport::No) {
147482acea6STrond Norbye         return;
148482acea6STrond Norbye     }
149482acea6STrond Norbye 
1505597a9abSTrond Norbye     document.info.datatype = cb::mcbp::Datatype::Raw;
151482acea6STrond Norbye     document.value.clear();
1525597a9abSTrond Norbye     document.value.resize(21 * 1024 * 1024);
1535597a9abSTrond Norbye     document.compress();
154482acea6STrond Norbye     try {
155cc0ee8fdSTrond Norbye         userConnection->mutateWithMeta(
156cf97e679STrond Norbye                 document, Vbid(0), cb::mcbp::cas::Wildcard, 1, 0, {});
157482acea6STrond Norbye         FAIL() << "It should not be possible to store documents which exceeds "
158482acea6STrond Norbye                   "the max document size";
159482acea6STrond Norbye     } catch (const ConnectionError& error) {
160482acea6STrond Norbye         EXPECT_EQ(cb::mcbp::Status::E2big, error.getReason());
161482acea6STrond Norbye     }
162482acea6STrond Norbye }
163482acea6STrond Norbye 
164482acea6STrond Norbye TEST_P(WithMetaTest, MB36304_DocumentMaxSizeWithXattr) {
165482acea6STrond Norbye     TESTAPP_SKIP_IF_UNSUPPORTED(cb::mcbp::ClientOpcode::SetWithMeta);
166482acea6STrond Norbye     if (::testing::get<1>(GetParam()) == XattrSupport::No) {
167482acea6STrond Norbye         return;
168482acea6STrond Norbye     }
169482acea6STrond Norbye 
170482acea6STrond Norbye     document.value.clear();
171482acea6STrond Norbye     cb::xattr::Blob blob;
172482acea6STrond Norbye     blob.set("_sys", R"({"author":"bubba"})");
173482acea6STrond Norbye     auto xattrValue = blob.finalize();
174482acea6STrond Norbye     std::copy(xattrValue.begin(),
175482acea6STrond Norbye               xattrValue.end(),
176482acea6STrond Norbye               std::back_inserter(document.value));
177482acea6STrond Norbye 
178482acea6STrond Norbye     document.value.resize((20 * 1024 * 1024) + xattrValue.size());
179482acea6STrond Norbye     document.info.datatype = cb::mcbp::Datatype::Xattr;
180cc0ee8fdSTrond Norbye     userConnection->mutateWithMeta(
181cf97e679STrond Norbye             document, Vbid(0), cb::mcbp::cas::Wildcard, 1, 0, {});
182cc0ee8fdSTrond Norbye     userConnection->remove(name, Vbid(0));
183482acea6STrond Norbye }
18408085d71STrond Norbye 
18508085d71STrond Norbye TEST_P(WithMetaTest, MB36321_DeleteWithMetaRefuseUserXattrs) {
18608085d71STrond Norbye     TESTAPP_SKIP_IF_UNSUPPORTED(cb::mcbp::ClientOpcode::DelWithMeta);
18708085d71STrond Norbye     if (::testing::get<1>(GetParam()) == XattrSupport::No ||
18808085d71STrond Norbye         ::testing::get<2>(GetParam()) == ClientJSONSupport::No) {
18908085d71STrond Norbye         return;
19008085d71STrond Norbye     }
19108085d71STrond Norbye 
1921d64ce3fSTrond Norbye     adminConnection->executeInBucket(bucketName, [](auto& connection) {
19354794ecaSPaolo Cocchi         const auto setParam = BinprotSetParamCommand(
19454794ecaSPaolo Cocchi                 cb::mcbp::request::SetParamPayload::Type::Flush,
1958d13b011SPaolo Cocchi                 "allow_sanitize_value_in_deletion",
19654794ecaSPaolo Cocchi                 "false");
1971d64ce3fSTrond Norbye         const auto resp = BinprotMutationResponse(connection.execute(setParam));
19854794ecaSPaolo Cocchi         ASSERT_EQ(cb::mcbp::Status::Success, resp.getStatus());
1991d64ce3fSTrond Norbye     });
20054794ecaSPaolo Cocchi 
20108085d71STrond Norbye     cb::xattr::Blob blob;
20208085d71STrond Norbye     blob.set("user", R"({"band":"Steel Panther"})");
20308085d71STrond Norbye     auto xattrValue = blob.finalize();
20408085d71STrond Norbye 
20508085d71STrond Norbye     document.value.clear();
20608085d71STrond Norbye     std::copy(xattrValue.begin(),
20708085d71STrond Norbye               xattrValue.end(),
20808085d71STrond Norbye               std::back_inserter(document.value));
20908085d71STrond Norbye     document.value.append(R"({"Bug":"MB-36321"})");
21008085d71STrond Norbye     using cb::mcbp::Datatype;
21108085d71STrond Norbye     document.info.datatype =
21208085d71STrond Norbye             Datatype(uint8_t(Datatype::Xattr) | uint8_t(Datatype::JSON));
21308085d71STrond Norbye 
21408085d71STrond Norbye     BinprotDelWithMetaCommand cmd(document, Vbid(0), 0, 0, 1, 0);
215cc0ee8fdSTrond Norbye     const auto rsp = BinprotMutationResponse(userConnection->execute(cmd));
21608085d71STrond Norbye     ASSERT_FALSE(rsp.isSuccess()) << rsp.getStatus();
21708085d71STrond Norbye     auto error = nlohmann::json::parse(rsp.getDataString());
21808085d71STrond Norbye 
21908085d71STrond Norbye     ASSERT_EQ(
220233ea88eSPaolo Cocchi             "It is only possible to specify Xattrs as a value to "
221233ea88eSPaolo Cocchi             "DeleteWithMeta",
22208085d71STrond Norbye             error["error"]["context"]);
22308085d71STrond Norbye }
22408085d71STrond Norbye 
22508085d71STrond Norbye TEST_P(WithMetaTest, MB36321_DeleteWithMetaAllowSystemXattrs) {
22608085d71STrond Norbye     TESTAPP_SKIP_IF_UNSUPPORTED(cb::mcbp::ClientOpcode::DelWithMeta);
22708085d71STrond Norbye     if (::testing::get<1>(GetParam()) == XattrSupport::No ||
22808085d71STrond Norbye         ::testing::get<2>(GetParam()) == ClientJSONSupport::No) {
22908085d71STrond Norbye         return;
23008085d71STrond Norbye     }
23108085d71STrond Norbye 
23208085d71STrond Norbye     cb::xattr::Blob blob;
23308085d71STrond Norbye     blob.set("_sys", R"({"author":"bubba"})");
23408085d71STrond Norbye     auto xattrValue = blob.finalize();
23508085d71STrond Norbye 
23608085d71STrond Norbye     document.value.clear();
23708085d71STrond Norbye     std::copy(xattrValue.begin(),
23808085d71STrond Norbye               xattrValue.end(),
23908085d71STrond Norbye               std::back_inserter(document.value));
24008085d71STrond Norbye     document.info.datatype = cb::mcbp::Datatype::Xattr;
24108085d71STrond Norbye 
24208085d71STrond Norbye     BinprotDelWithMetaCommand cmd(document, Vbid(0), 0, 0, 1, 0);
243cc0ee8fdSTrond Norbye     const auto rsp = BinprotMutationResponse(userConnection->execute(cmd));
24408085d71STrond Norbye     ASSERT_TRUE(rsp.isSuccess()) << rsp.getStatus();
24508085d71STrond Norbye 
24608085d71STrond Norbye     // The system xattr should be there
24705219679STrond Norbye     auto sresp = subdoc(cb::mcbp::ClientOpcode::SubdocGet,
24808085d71STrond Norbye                         name,
24908085d71STrond Norbye                         "_sys.author",
25008085d71STrond Norbye                         {},
25108085d71STrond Norbye                         SUBDOC_FLAG_XATTR_PATH,
2528bfdba48STrond Norbye                         cb::mcbp::subdoc::doc_flag::AccessDeleted);
25308085d71STrond Norbye     EXPECT_TRUE(sresp.isSuccess()) << sresp.getStatus();
25408085d71STrond Norbye }
255233ea88eSPaolo Cocchi 
256b08424f8SPaolo Cocchi void WithMetaTest::testDeleteWithMetaAcceptsUserXattrs(bool allowValuePruning,
257b08424f8SPaolo Cocchi                                                        bool compressed) {
258233ea88eSPaolo Cocchi     TESTAPP_SKIP_IF_UNSUPPORTED(cb::mcbp::ClientOpcode::DelWithMeta);
259233ea88eSPaolo Cocchi     if (::testing::get<1>(GetParam()) == XattrSupport::No ||
260233ea88eSPaolo Cocchi         ::testing::get<2>(GetParam()) == ClientJSONSupport::No) {
261233ea88eSPaolo Cocchi         return;
262233ea88eSPaolo Cocchi     }
263233ea88eSPaolo Cocchi 
2641d64ce3fSTrond Norbye     adminConnection->executeInBucket(bucketName, [&](auto& connection) {
265233ea88eSPaolo Cocchi         const auto setParam = BinprotSetParamCommand(
266233ea88eSPaolo Cocchi                 cb::mcbp::request::SetParamPayload::Type::Flush,
2678d13b011SPaolo Cocchi                 "allow_sanitize_value_in_deletion",
268233ea88eSPaolo Cocchi                 allowValuePruning ? "true" : "false");
2691d64ce3fSTrond Norbye         const auto resp = BinprotMutationResponse(connection.execute(setParam));
270233ea88eSPaolo Cocchi         ASSERT_EQ(cb::mcbp::Status::Success, resp.getStatus());
2711d64ce3fSTrond Norbye     });
272233ea88eSPaolo Cocchi 
273233ea88eSPaolo Cocchi     // Value with User/Sys Xattrs and no Body
274233ea88eSPaolo Cocchi     cb::xattr::Blob blob;
275233ea88eSPaolo Cocchi     blob.set("user", R"({"a":"b"})");
276233ea88eSPaolo Cocchi     blob.set("_sys", R"({"c":"d"})");
277233ea88eSPaolo Cocchi     const auto xattrs = blob.finalize();
278233ea88eSPaolo Cocchi     document.value.clear();
279233ea88eSPaolo Cocchi     std::copy(xattrs.begin(), xattrs.end(), std::back_inserter(document.value));
280b08424f8SPaolo Cocchi     using Datatype = cb::mcbp::Datatype;
281b08424f8SPaolo Cocchi     document.info.datatype = Datatype::Xattr;
282b08424f8SPaolo Cocchi 
283b08424f8SPaolo Cocchi     if (compressed) {
2845597a9abSTrond Norbye         document.compress();
285b08424f8SPaolo Cocchi     }
286233ea88eSPaolo Cocchi 
287233ea88eSPaolo Cocchi     BinprotDelWithMetaCommand delWithMeta(
288233ea88eSPaolo Cocchi             document, Vbid(0), 0, 0 /*delTime*/, 1 /*seqno*/, 0 /*opCas*/);
289cc0ee8fdSTrond Norbye     const auto resp =
290cc0ee8fdSTrond Norbye             BinprotMutationResponse(userConnection->execute(delWithMeta));
291b08424f8SPaolo Cocchi     const auto expectedStatus = compressed && ::testing::get<3>(GetParam()) ==
292b08424f8SPaolo Cocchi                                                         ClientSnappySupport::No
293b08424f8SPaolo Cocchi                                         ? cb::mcbp::Status::Einval
294b08424f8SPaolo Cocchi                                         : cb::mcbp::Status::Success;
295b08424f8SPaolo Cocchi     EXPECT_EQ(expectedStatus, resp.getStatus());
296233ea88eSPaolo Cocchi }
297233ea88eSPaolo Cocchi 
298233ea88eSPaolo Cocchi TEST_P(WithMetaTest, DeleteWithMetaAcceptsUserXattrs) {
299233ea88eSPaolo Cocchi     testDeleteWithMetaAcceptsUserXattrs(false);
300233ea88eSPaolo Cocchi }
301233ea88eSPaolo Cocchi 
302233ea88eSPaolo Cocchi TEST_P(WithMetaTest, DeleteWithMetaAcceptsUserXattrs_AllowValuePruning) {
303233ea88eSPaolo Cocchi     testDeleteWithMetaAcceptsUserXattrs(true);
304233ea88eSPaolo Cocchi }
305233ea88eSPaolo Cocchi 
306b08424f8SPaolo Cocchi TEST_P(WithMetaTest, DeleteWithMetaAcceptsUserXattrs_Compressed) {
307b08424f8SPaolo Cocchi     testDeleteWithMetaAcceptsUserXattrs(false, true);
308b08424f8SPaolo Cocchi }
309b08424f8SPaolo Cocchi 
310233ea88eSPaolo Cocchi void WithMetaTest::testDeleteWithMetaRejectsBody(bool allowValuePruning,
311233ea88eSPaolo Cocchi                                                  bool dtXattr) {
312233ea88eSPaolo Cocchi     TESTAPP_SKIP_IF_UNSUPPORTED(cb::mcbp::ClientOpcode::DelWithMeta);
313233ea88eSPaolo Cocchi     if (::testing::get<1>(GetParam()) == XattrSupport::No ||
314233ea88eSPaolo Cocchi         ::testing::get<2>(GetParam()) == ClientJSONSupport::No) {
315233ea88eSPaolo Cocchi         return;
316233ea88eSPaolo Cocchi     }
317233ea88eSPaolo Cocchi 
3181d64ce3fSTrond Norbye     adminConnection->executeInBucket(bucketName, [&](auto& connection) {
319233ea88eSPaolo Cocchi         const auto setParam = BinprotSetParamCommand(
320233ea88eSPaolo Cocchi                 cb::mcbp::request::SetParamPayload::Type::Flush,
3218d13b011SPaolo Cocchi                 "allow_sanitize_value_in_deletion",
322233ea88eSPaolo Cocchi                 allowValuePruning ? "true" : "false");
3231d64ce3fSTrond Norbye         const auto resp = BinprotMutationResponse(connection.execute(setParam));
324233ea88eSPaolo Cocchi         ASSERT_EQ(cb::mcbp::Status::Success, resp.getStatus());
3251d64ce3fSTrond Norbye     });
326233ea88eSPaolo Cocchi 
327233ea88eSPaolo Cocchi     // Value with User/Sys Xattrs and Body
328233ea88eSPaolo Cocchi     if (dtXattr) {
329233ea88eSPaolo Cocchi         cb::xattr::Blob blob;
330233ea88eSPaolo Cocchi         blob.set("user", R"({"a":"b"})");
331233ea88eSPaolo Cocchi         blob.set("_sys", R"({"c":"d"})");
332233ea88eSPaolo Cocchi         const auto xattrs = blob.finalize();
333233ea88eSPaolo Cocchi         document.value.clear();
334233ea88eSPaolo Cocchi         std::copy(xattrs.begin(),
335233ea88eSPaolo Cocchi                   xattrs.end(),
336233ea88eSPaolo Cocchi                   std::back_inserter(document.value));
337233ea88eSPaolo Cocchi         document.value.append("body");
338233ea88eSPaolo Cocchi         document.info.datatype = cb::mcbp::Datatype::Xattr;
339233ea88eSPaolo Cocchi     } else {
340233ea88eSPaolo Cocchi         document.value = "body";
341233ea88eSPaolo Cocchi         document.info.datatype = cb::mcbp::Datatype::Raw;
342233ea88eSPaolo Cocchi     }
343233ea88eSPaolo Cocchi 
344233ea88eSPaolo Cocchi     BinprotDelWithMetaCommand delWithMeta(
345233ea88eSPaolo Cocchi             document, Vbid(0), 0, 0 /*delTime*/, 1 /*seqno*/, 0 /*opCas*/);
346cc0ee8fdSTrond Norbye     const auto resp =
347cc0ee8fdSTrond Norbye             BinprotMutationResponse(userConnection->execute(delWithMeta));
348233ea88eSPaolo Cocchi     if (allowValuePruning) {
349233ea88eSPaolo Cocchi         ASSERT_EQ(cb::mcbp::Status::Success, resp.getStatus());
350233ea88eSPaolo Cocchi     } else {
351233ea88eSPaolo Cocchi         ASSERT_EQ(cb::mcbp::Status::Einval, resp.getStatus());
352233ea88eSPaolo Cocchi         ASSERT_TRUE(
353233ea88eSPaolo Cocchi                 resp.getDataString().find("only possible to specify Xattrs") !=
354233ea88eSPaolo Cocchi                 std::string::npos);
355233ea88eSPaolo Cocchi     }
356233ea88eSPaolo Cocchi }
357233ea88eSPaolo Cocchi 
358233ea88eSPaolo Cocchi TEST_P(WithMetaTest, DeleteWithMetaRejectsBody_AllowValuePruning) {
359233ea88eSPaolo Cocchi     testDeleteWithMetaRejectsBody(true, false);
360233ea88eSPaolo Cocchi }
361233ea88eSPaolo Cocchi 
362233ea88eSPaolo Cocchi TEST_P(WithMetaTest, DeleteWithMetaRejectsBody) {
363233ea88eSPaolo Cocchi     testDeleteWithMetaRejectsBody(false, false);
364233ea88eSPaolo Cocchi }
365233ea88eSPaolo Cocchi 
366233ea88eSPaolo Cocchi TEST_P(WithMetaTest, DeleteWithMetaRejectsBody_AllowValuePruning_DTXattr) {
367233ea88eSPaolo Cocchi     testDeleteWithMetaRejectsBody(true, true);
368233ea88eSPaolo Cocchi }
369233ea88eSPaolo Cocchi 
370233ea88eSPaolo Cocchi TEST_P(WithMetaTest, DeleteWithMetaRejectsBody_DTXattr) {
371233ea88eSPaolo Cocchi     testDeleteWithMetaRejectsBody(false, true);
372233ea88eSPaolo Cocchi }