@@ -1536,3 +1536,101 @@ TEST_P(XattrTest, MB_28524_TestReplaceWithXattrUncompressed) {
15361536TEST_P (XattrTest, MB_28524_TestReplaceWithXattrCompressed) {
15371537 doReplaceWithXattrTest (true );
15381538}
1539+
1540+ /* *
1541+ * If the client tries to fetch a mix of multiple virtual xattrs it might not
1542+ * work as expected. Ex:
1543+ *
1544+ * $document
1545+ * tnx
1546+ * will work, but
1547+ *
1548+ * tnx
1549+ * $document
1550+ * will not work. In addition
1551+ *
1552+ * $XTOC
1553+ * tnx
1554+ * returns "null" for the toc
1555+ */
1556+ TEST_P (XattrTest, MB35079_virtual_xattr_mix) {
1557+ // Store the document we want to operate on
1558+ {
1559+ BinprotSubdocMultiMutationCommand cmd;
1560+ cmd.setKey (name);
1561+ cmd.addMutation (cb::mcbp::ClientOpcode::SubdocDictUpsert,
1562+ SUBDOC_FLAG_XATTR_PATH,
1563+ " tnx" ,
1564+ " {\" id\" :666}" );
1565+ cmd.addMutation (cb::mcbp::ClientOpcode::SubdocDictUpsert,
1566+ SUBDOC_FLAG_MKDIR_P,
1567+ " value" ,
1568+ R"( "value")" );
1569+ auto & conn = getConnection ();
1570+ ASSERT_EQ (cb::mcbp::Status::Success, conn.execute (cmd).getStatus ());
1571+ }
1572+
1573+ // Problem 1 : The order of the virtual xattr and key matters:
1574+ {
1575+ BinprotSubdocMultiLookupCommand cmd;
1576+ cmd.setKey (name);
1577+ cmd.addGet (" tnx" , SUBDOC_FLAG_XATTR_PATH);
1578+ cmd.addGet (" $document.CAS" , SUBDOC_FLAG_XATTR_PATH);
1579+ cmd.addGet (" value" , SUBDOC_FLAG_NONE);
1580+
1581+ auto & conn = getConnection ();
1582+ BinprotSubdocMultiLookupResponse resp{conn.execute (cmd)};
1583+ ASSERT_EQ (cb::mcbp::Status::Success, resp.getStatus ());
1584+
1585+ auto & results = resp.getResults ();
1586+ EXPECT_EQ (cb::mcbp::Status::Success, results[0 ].status );
1587+ EXPECT_EQ (R"( {"id":666})" , results[0 ].value );
1588+ EXPECT_EQ (cb::mcbp::Status::Success, results[1 ].status );
1589+ // We can't really check the CAS, but it should be a hex value
1590+ EXPECT_EQ (0 , results[1 ].value .find (" \" 0x" ));
1591+ EXPECT_EQ (cb::mcbp::Status::Success, results[2 ].status );
1592+ EXPECT_EQ (R"( "value")" , results[2 ].value );
1593+ }
1594+ // Try it with cas first and then the xattr
1595+ {
1596+ BinprotSubdocMultiLookupCommand cmd;
1597+ cmd.setKey (name);
1598+ cmd.addGet (" $document.CAS" , SUBDOC_FLAG_XATTR_PATH);
1599+ cmd.addGet (" tnx" , SUBDOC_FLAG_XATTR_PATH);
1600+ cmd.addGet (" value" , SUBDOC_FLAG_NONE);
1601+
1602+ auto & conn = getConnection ();
1603+ BinprotSubdocMultiLookupResponse resp{conn.execute (cmd)};
1604+ ASSERT_EQ (cb::mcbp::Status::Success, resp.getStatus ());
1605+
1606+ auto & results = resp.getResults ();
1607+ EXPECT_EQ (cb::mcbp::Status::Success, results[0 ].status );
1608+ // We can't really check the CAS, but it should be a hex value
1609+ EXPECT_EQ (0 , results[0 ].value .find (" \" 0x" ));
1610+ EXPECT_EQ (cb::mcbp::Status::Success, results[1 ].status );
1611+ EXPECT_EQ (R"( {"id":666})" , results[1 ].value );
1612+ EXPECT_EQ (cb::mcbp::Status::Success, results[2 ].status );
1613+ EXPECT_EQ (R"( "value")" , results[2 ].value );
1614+ }
1615+
1616+ // Problem 2 : Requesting XTOC with another xattr fails to populate XTOC
1617+ {
1618+ BinprotSubdocMultiLookupCommand cmd;
1619+ cmd.setKey (name);
1620+ cmd.addGet (" $XTOC" , SUBDOC_FLAG_XATTR_PATH);
1621+ cmd.addGet (" tnx" , SUBDOC_FLAG_XATTR_PATH);
1622+ cmd.addGet (" value" , SUBDOC_FLAG_NONE);
1623+
1624+ auto & conn = getConnection ();
1625+ BinprotSubdocMultiLookupResponse resp{conn.execute (cmd)};
1626+ ASSERT_EQ (cb::mcbp::Status::Success, resp.getStatus ());
1627+
1628+ auto & results = resp.getResults ();
1629+ EXPECT_EQ (cb::mcbp::Status::Success, results[0 ].status );
1630+ EXPECT_EQ (R"( ["tnx"])" , results[0 ].value );
1631+ EXPECT_EQ (cb::mcbp::Status::Success, results[1 ].status );
1632+ EXPECT_EQ (R"( {"id":666})" , results[1 ].value );
1633+ EXPECT_EQ (cb::mcbp::Status::Success, results[2 ].status );
1634+ EXPECT_EQ (R"( "value")" , results[2 ].value );
1635+ }
1636+ }
0 commit comments