1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2016 Couchbase, Inc.
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  */
17 
18 #include "testapp.h"
19 #include "testapp_client_test.h"
20 
21 #include <array>
22 
23 class FlushTest : public TestappClientTest {
24 protected:
25     void SetUp() override {
26         TestappClientTest::SetUp();
27 
28         conn = &getAdminConnection();
29         conn->selectBucket("default");
30 
31         // Store our lone document
32         Document doc;
33         doc.info.datatype = cb::mcbp::Datatype::Raw;
34         doc.info.cas = 0;
35         doc.info.flags = 0;
36         doc.info.id = key;
37         conn->mutate(doc, vbid, MutationType::Set);
38     }
39 
40     void TearDown() override {
41         try {
42             conn->remove(key, vbid, 0);
43         } catch (ConnectionError& err) {
44             if (!err.isNotFound()) {
45                 throw err;
46             }
47         }
48         conn = nullptr;
49         TestappClientTest::TearDown();
50     }
51 
get(BinprotResponse& resp)52     protocol_binary_response_status get(BinprotResponse& resp) {
53         resp.clear();
54         BinprotGetCommand cmd;
55         cmd.setKey(key);
56         cmd.setVBucket(vbid);
57         conn->executeCommand(cmd, resp);
58         return resp.getStatus();
59     }
60 
61     const char *key = "test_flush";
62     const uint16_t vbid = 0;
63     MemcachedConnection* conn = nullptr;
64 };
65 
66 INSTANTIATE_TEST_CASE_P(TransportProtocols,
67                         FlushTest,
68                         ::testing::Values(TransportProtocols::McbpPlain,
69                                           TransportProtocols::McbpIpv6Plain,
70                                           TransportProtocols::McbpSsl,
71                                           TransportProtocols::McbpIpv6Ssl
72                                          ),
73                         ::testing::PrintToStringParamName());
74 
TEST_P(FlushTest, Flush)75 TEST_P(FlushTest, Flush) {
76     TESTAPP_SKIP_IF_UNSUPPORTED(PROTOCOL_BINARY_CMD_FLUSH);
77     BinprotGenericCommand command(PROTOCOL_BINARY_CMD_FLUSH);
78     BinprotResponse response;
79     conn->executeCommand(command, response);
80     ASSERT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, response.getStatus());
81     ASSERT_EQ(PROTOCOL_BINARY_RESPONSE_KEY_ENOENT, get(response));
82 }
83 
TEST_P(FlushTest, FlushQ)84 TEST_P(FlushTest, FlushQ) {
85     TESTAPP_SKIP_IF_UNSUPPORTED(PROTOCOL_BINARY_CMD_FLUSH);
86     BinprotGenericCommand command(PROTOCOL_BINARY_CMD_FLUSHQ);
87     BinprotResponse response;
88     conn->sendCommand(command);
89     ASSERT_EQ(PROTOCOL_BINARY_RESPONSE_KEY_ENOENT, get(response));
90 }
91 
TEST_P(FlushTest, FlushWithExtlen)92 TEST_P(FlushTest, FlushWithExtlen) {
93     TESTAPP_SKIP_IF_UNSUPPORTED(PROTOCOL_BINARY_CMD_FLUSH);
94     BinprotGenericCommand command(PROTOCOL_BINARY_CMD_FLUSH);
95     command.setExtrasValue(uint32_t(htonl(0)));
96 
97     // Ensure it still works
98     BinprotResponse response;
99     conn->executeCommand(command, response);
100     ASSERT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, response.getStatus());
101     ASSERT_EQ(PROTOCOL_BINARY_RESPONSE_KEY_ENOENT, get(response));
102 }
103 
TEST_P(FlushTest, FlushQWithExtlen)104 TEST_P(FlushTest, FlushQWithExtlen) {
105     TESTAPP_SKIP_IF_UNSUPPORTED(PROTOCOL_BINARY_CMD_FLUSH);
106     BinprotGenericCommand command(PROTOCOL_BINARY_CMD_FLUSHQ);
107     BinprotResponse response;
108     command.setExtrasValue(static_cast<uint32_t>(htonl(0)));
109     conn->sendCommand(command);
110 
111     ASSERT_EQ(PROTOCOL_BINARY_RESPONSE_KEY_ENOENT, get(response));
112 }
113 
TEST_P(FlushTest, DISABLED_DelayedFlushNotSupported)114 TEST_P(FlushTest, DISABLED_DelayedFlushNotSupported) {
115     TESTAPP_SKIP_IF_UNSUPPORTED(PROTOCOL_BINARY_CMD_FLUSH);
116     BinprotGenericCommand command;
117     BinprotResponse response;
118 
119     command.setExtrasValue(static_cast<uint32_t>(htonl(2)));
120 
121     std::array<protocol_binary_command, 2> commands{{
122         PROTOCOL_BINARY_CMD_FLUSH, PROTOCOL_BINARY_CMD_FLUSHQ
123     }};
124     for (auto op : commands) {
125         conn->executeCommand(command.setOp(op), response);
126         ASSERT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, response.getStatus());
127 
128         conn->reconnect();
129         ASSERT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, get(response));
130     }
131 }
132