xref: /5.5.2/kv_engine/tests/mcbp/mcbp_test.cc (revision 84af6315)
1/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 *     Copyright 2015 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#include "config.h"
18#include "mcbp_test.h"
19#include "utilities/protocol2text.h"
20
21#include <event2/event.h>
22#include <mcbp/protocol/header.h>
23#include <memcached/protocol_binary.h>
24#include <platform/make_unique.h>
25#include <gsl/gsl>
26
27/**
28 * Test all of the command validators we've got to ensure that they
29 * catch broken packets. There is still a high number of commands we
30 * don't have any command validators for...
31 */
32namespace mcbp {
33namespace test {
34
35ValidatorTest::ValidatorTest()
36    : request(*reinterpret_cast<protocol_binary_request_no_extras*>(blob)) {
37}
38
39void ValidatorTest::SetUp() {
40    settings.setXattrEnabled(true);
41    McbpValidatorChains::initializeMcbpValidatorChains(validatorChains);
42    memset(request.bytes, 0, sizeof(request));
43    request.message.header.request.magic = PROTOCOL_BINARY_REQ;
44    request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
45}
46
47/**
48 * Mock the cookie class and override the getPacket method so that we
49 * may use the buffer directly instead of having to insert it into the read/
50 * write buffers of the underlying connection
51 */
52class MockCookie : public Cookie {
53public:
54    MockCookie(Connection& connection, cb::const_byte_buffer buffer)
55        : Cookie(connection) {
56        setPacket(PacketContent::Full, buffer);
57    }
58};
59
60protocol_binary_response_status
61ValidatorTest::validate(protocol_binary_command opcode, void* packet) {
62    // Mockup a McbpConnection and Cookie for the validator chain
63    connection.enableDatatype(cb::mcbp::Feature::XATTR);
64    const auto& req = *reinterpret_cast<const cb::mcbp::Header*>(packet);
65    const size_t size = sizeof(req) + req.getBodylen();
66    cb::const_byte_buffer buffer{static_cast<uint8_t*>(packet), size};
67    MockCookie cookie(connection, buffer);
68    return validatorChains.invoke(opcode, cookie);
69}
70
71enum class GetOpcodes : uint8_t {
72    Get = PROTOCOL_BINARY_CMD_GET,
73    GetQ = PROTOCOL_BINARY_CMD_GETQ,
74    GetK = PROTOCOL_BINARY_CMD_GETK,
75    GetKQ = PROTOCOL_BINARY_CMD_GETKQ,
76    GetMeta = PROTOCOL_BINARY_CMD_GET_META,
77    GetQMeta = PROTOCOL_BINARY_CMD_GETQ_META
78};
79
80std::string to_string(const GetOpcodes& opcode) {
81#ifdef JETBRAINS_CLION_IDE
82    // CLion don't properly parse the output when the
83    // output gets written as the string instead of the
84    // number. This makes it harder to debug the tests
85    // so let's just disable it while we're waiting
86    // for them to supply a fix.
87    // See https://youtrack.jetbrains.com/issue/CPP-6039
88    return std::to_string(static_cast<int>(opcode));
89#else
90    switch (opcode) {
91    case GetOpcodes::Get:
92        return "Get";
93    case GetOpcodes::GetQ:
94        return "GetQ";
95    case GetOpcodes::GetK:
96        return "GetK";
97    case GetOpcodes::GetKQ:
98        return "GetKQ";
99    case GetOpcodes::GetMeta:
100        return "GetMeta";
101    case GetOpcodes::GetQMeta:
102        return "GetQMeta";
103    }
104    throw std::invalid_argument("to_string(): unknown opcode");
105#endif
106}
107
108std::ostream& operator<<(std::ostream& os, const GetOpcodes& o) {
109    os << to_string(o);
110    return os;
111}
112
113// Test the validators for GET, GETQ, GETK, GETKQ, GET_META and GETQ_META
114class GetValidatorTest : public ValidatorTest,
115                         public ::testing::WithParamInterface<GetOpcodes> {
116public:
117    void SetUp() override {
118        ValidatorTest::SetUp();
119        memset(&request, 0, sizeof(request));
120        request.message.header.request.magic = PROTOCOL_BINARY_REQ;
121        request.message.header.request.extlen = 0;
122        request.message.header.request.keylen = htons(10);
123        request.message.header.request.bodylen = htonl(10);
124        request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
125    }
126
127    GetValidatorTest()
128        : ValidatorTest(),
129          bodylen(request.message.header.request.bodylen) {
130        // empty
131    }
132
133protected:
134
135    protocol_binary_response_status validateExtendedExtlen(uint8_t version) {
136        bodylen = htonl(ntohl(bodylen) + 1);
137        request.message.header.request.extlen = 1;
138        blob[sizeof(protocol_binary_request_get)] = version;
139        return validate();
140    }
141
142    protocol_binary_response_status validate() {
143        auto opcode = (protocol_binary_command)GetParam();
144        return ValidatorTest::validate(opcode, static_cast<void*>(&request));
145    }
146
147    uint32_t& bodylen;
148};
149
150TEST_P(GetValidatorTest, CorrectMessage) {
151    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
152}
153
154TEST_P(GetValidatorTest, InvalidMagic) {
155    request.message.header.request.magic = 0;
156    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
157}
158
159TEST_P(GetValidatorTest, ExtendedExtlenV1) {
160    switch (GetParam()) {
161    case GetOpcodes::Get:
162    case GetOpcodes::GetQ:
163    case GetOpcodes::GetK:
164    case GetOpcodes::GetKQ:
165        // Extended extlen is only supported for *Meta
166        return;
167    case GetOpcodes::GetMeta:
168    case GetOpcodes::GetQMeta:
169        EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validateExtendedExtlen(1));
170        break;
171    }
172}
173
174TEST_P(GetValidatorTest, ExtendedExtlenV2) {
175    switch (GetParam()) {
176    case GetOpcodes::Get:
177    case GetOpcodes::GetQ:
178    case GetOpcodes::GetK:
179    case GetOpcodes::GetKQ:
180        // Extended extlen is only supported for *Meta
181        return;
182    case GetOpcodes::GetMeta:
183    case GetOpcodes::GetQMeta:
184        EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validateExtendedExtlen(2));
185        break;
186    }
187}
188
189TEST_P(GetValidatorTest, InvalidExtendedExtlenVersion) {
190    switch (GetParam()) {
191    case GetOpcodes::Get:
192    case GetOpcodes::GetQ:
193    case GetOpcodes::GetK:
194    case GetOpcodes::GetKQ:
195        // Extended extlen is only supported for *Meta
196        return;
197    case GetOpcodes::GetMeta:
198    case GetOpcodes::GetQMeta:
199        EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validateExtendedExtlen(3));
200        break;
201    }
202}
203
204TEST_P(GetValidatorTest, InvalidExtlen) {
205    bodylen = htonl(ntohl(bodylen) + 21);
206    request.message.header.request.extlen = 21;
207    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
208}
209
210TEST_P(GetValidatorTest, NoKey) {
211    request.message.header.request.keylen = 0;
212    bodylen = 0;
213    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
214}
215
216TEST_P(GetValidatorTest, InvalidDatatype) {
217    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
218    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
219}
220
221TEST_P(GetValidatorTest, InvalidCas) {
222    request.message.header.request.cas = 1;
223    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
224}
225
226
227// @todo add test case for the extra legal modes for the
228// get meta case
229
230INSTANTIATE_TEST_CASE_P(GetOpcodes,
231                        GetValidatorTest,
232                        ::testing::Values(GetOpcodes::Get,
233                                          GetOpcodes::GetQ,
234                                          GetOpcodes::GetK,
235                                          GetOpcodes::GetKQ,
236                                          GetOpcodes::GetMeta,
237                                          GetOpcodes::GetQMeta),
238                        ::testing::PrintToStringParamName());
239
240// Test ADD & ADDQ
241class AddValidatorTest : public ValidatorTest {
242    void SetUp() override {
243        ValidatorTest::SetUp();
244        request.message.header.request.extlen = 8;
245        request.message.header.request.keylen = htons(10);
246        request.message.header.request.bodylen = htonl(20);
247    }
248
249protected:
250    int validate(protocol_binary_command opcode) {
251        return ValidatorTest::validate(opcode, static_cast<void*>(&request));
252    }
253};
254
255TEST_F(AddValidatorTest, CorrectMessage) {
256    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
257              validate(PROTOCOL_BINARY_CMD_ADD));
258    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
259              validate(PROTOCOL_BINARY_CMD_ADDQ));
260}
261
262TEST_F(AddValidatorTest, NoValue) {
263    request.message.header.request.bodylen = htonl(10);
264    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
265              validate(PROTOCOL_BINARY_CMD_ADD));
266    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
267              validate(PROTOCOL_BINARY_CMD_ADDQ));
268}
269
270TEST_F(AddValidatorTest, InvalidMagic) {
271    request.message.header.request.magic = 0;
272    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
273              validate(PROTOCOL_BINARY_CMD_ADD));
274    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
275              validate(PROTOCOL_BINARY_CMD_ADDQ));
276}
277
278TEST_F(AddValidatorTest, InvalidExtlen) {
279    request.message.header.request.extlen = 21;
280    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
281              validate(PROTOCOL_BINARY_CMD_ADD));
282    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
283              validate(PROTOCOL_BINARY_CMD_ADDQ));
284}
285
286TEST_F(AddValidatorTest, NoKey) {
287    request.message.header.request.keylen = 0;
288    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
289              validate(PROTOCOL_BINARY_CMD_ADD));
290    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
291              validate(PROTOCOL_BINARY_CMD_ADDQ));
292}
293
294TEST_F(AddValidatorTest, InvalidCas) {
295    request.message.header.request.cas = 1;
296    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
297              validate(PROTOCOL_BINARY_CMD_ADD));
298    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
299              validate(PROTOCOL_BINARY_CMD_ADDQ));
300}
301
302// Test SET, SETQ, REPLACE, REPLACEQ
303class SetReplaceValidatorTest : public ValidatorTest {
304    void SetUp() override {
305        ValidatorTest::SetUp();
306        request.message.header.request.extlen = 8;
307        request.message.header.request.keylen = htons(10);
308        request.message.header.request.bodylen = htonl(20);
309    }
310
311protected:
312    int validate(protocol_binary_command opcode) {
313        return ValidatorTest::validate(opcode, static_cast<void*>(&request));
314    }
315};
316
317TEST_F(SetReplaceValidatorTest, CorrectMessage) {
318    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
319              validate(PROTOCOL_BINARY_CMD_SET));
320    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
321              validate(PROTOCOL_BINARY_CMD_SETQ));
322    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
323              validate(PROTOCOL_BINARY_CMD_REPLACE));
324    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
325              validate(PROTOCOL_BINARY_CMD_REPLACEQ));
326}
327
328TEST_F(SetReplaceValidatorTest, NoValue) {
329    request.message.header.request.bodylen = htonl(10);
330    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
331              validate(PROTOCOL_BINARY_CMD_SET));
332    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
333              validate(PROTOCOL_BINARY_CMD_SETQ));
334    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
335              validate(PROTOCOL_BINARY_CMD_REPLACE));
336    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
337              validate(PROTOCOL_BINARY_CMD_REPLACEQ));
338}
339
340TEST_F(SetReplaceValidatorTest, Cas) {
341    request.message.header.request.cas = 1;
342    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
343              validate(PROTOCOL_BINARY_CMD_SET));
344    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
345              validate(PROTOCOL_BINARY_CMD_SETQ));
346    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
347              validate(PROTOCOL_BINARY_CMD_REPLACE));
348    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
349              validate(PROTOCOL_BINARY_CMD_REPLACEQ));
350}
351
352TEST_F(SetReplaceValidatorTest, InvalidMagic) {
353    request.message.header.request.magic = 0;
354    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
355              validate(PROTOCOL_BINARY_CMD_SET));
356    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
357              validate(PROTOCOL_BINARY_CMD_SETQ));
358    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
359              validate(PROTOCOL_BINARY_CMD_REPLACE));
360    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
361              validate(PROTOCOL_BINARY_CMD_REPLACEQ));
362}
363
364TEST_F(SetReplaceValidatorTest, InvalidExtlen) {
365    request.message.header.request.extlen = 21;
366    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
367              validate(PROTOCOL_BINARY_CMD_SET));
368    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
369              validate(PROTOCOL_BINARY_CMD_SETQ));
370    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
371              validate(PROTOCOL_BINARY_CMD_REPLACE));
372    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
373              validate(PROTOCOL_BINARY_CMD_REPLACEQ));
374}
375
376TEST_F(SetReplaceValidatorTest, NoKey) {
377    request.message.header.request.keylen = 0;
378    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
379              validate(PROTOCOL_BINARY_CMD_SET));
380    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
381              validate(PROTOCOL_BINARY_CMD_SETQ));
382    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
383              validate(PROTOCOL_BINARY_CMD_REPLACE));
384    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
385              validate(PROTOCOL_BINARY_CMD_REPLACEQ));
386}
387
388// Test Append[q] and Prepend[q]
389class AppendPrependValidatorTest : public ValidatorTest {
390    void SetUp() override {
391        ValidatorTest::SetUp();
392        request.message.header.request.keylen = htons(10);
393        request.message.header.request.bodylen = htonl(20);
394    }
395
396protected:
397    int validate(protocol_binary_command opcode) {
398        return ValidatorTest::validate(opcode, static_cast<void*>(&request));
399    }
400};
401
402TEST_F(AppendPrependValidatorTest, CorrectMessage) {
403    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
404              validate(PROTOCOL_BINARY_CMD_APPEND));
405    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
406              validate(PROTOCOL_BINARY_CMD_APPENDQ));
407    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
408              validate(PROTOCOL_BINARY_CMD_PREPEND));
409    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
410              validate(PROTOCOL_BINARY_CMD_PREPENDQ));
411}
412
413TEST_F(AppendPrependValidatorTest, NoValue) {
414    request.message.header.request.bodylen = htonl(10);
415    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
416              validate(PROTOCOL_BINARY_CMD_APPEND));
417    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
418              validate(PROTOCOL_BINARY_CMD_APPENDQ));
419    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
420              validate(PROTOCOL_BINARY_CMD_PREPEND));
421    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
422              validate(PROTOCOL_BINARY_CMD_PREPENDQ));
423}
424
425TEST_F(AppendPrependValidatorTest, Cas) {
426    request.message.header.request.cas = 1;
427    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
428              validate(PROTOCOL_BINARY_CMD_APPEND));
429    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
430              validate(PROTOCOL_BINARY_CMD_APPENDQ));
431    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
432              validate(PROTOCOL_BINARY_CMD_PREPEND));
433    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
434              validate(PROTOCOL_BINARY_CMD_PREPENDQ));
435}
436
437TEST_F(AppendPrependValidatorTest, InvalidMagic) {
438    request.message.header.request.magic = 0;
439    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
440              validate(PROTOCOL_BINARY_CMD_APPEND));
441    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
442              validate(PROTOCOL_BINARY_CMD_APPENDQ));
443    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
444              validate(PROTOCOL_BINARY_CMD_PREPEND));
445    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
446              validate(PROTOCOL_BINARY_CMD_PREPENDQ));
447}
448
449TEST_F(AppendPrependValidatorTest, InvalidExtlen) {
450    request.message.header.request.extlen = 21;
451    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
452              validate(PROTOCOL_BINARY_CMD_APPEND));
453    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
454              validate(PROTOCOL_BINARY_CMD_APPENDQ));
455    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
456              validate(PROTOCOL_BINARY_CMD_PREPEND));
457    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
458              validate(PROTOCOL_BINARY_CMD_PREPENDQ));
459}
460
461TEST_F(AppendPrependValidatorTest, NoKey) {
462    request.message.header.request.keylen = 0;
463    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
464              validate(PROTOCOL_BINARY_CMD_APPEND));
465    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
466              validate(PROTOCOL_BINARY_CMD_APPENDQ));
467    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
468              validate(PROTOCOL_BINARY_CMD_PREPEND));
469    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
470              validate(PROTOCOL_BINARY_CMD_PREPENDQ));
471}
472
473// Test DELETE & DELETEQ
474class DeleteValidatorTest : public ValidatorTest {
475    void SetUp() override {
476        ValidatorTest::SetUp();
477        request.message.header.request.keylen = htons(10);
478        request.message.header.request.bodylen = htonl(10);
479    }
480
481protected:
482    int validate(protocol_binary_command opcode) {
483        return ValidatorTest::validate(opcode, static_cast<void*>(&request));
484    }
485};
486
487TEST_F(DeleteValidatorTest, CorrectMessage) {
488    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
489              validate(PROTOCOL_BINARY_CMD_DELETE));
490    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
491              validate(PROTOCOL_BINARY_CMD_DELETEQ));
492}
493
494TEST_F(DeleteValidatorTest, Cas) {
495    request.message.header.request.cas = 1;
496    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
497              validate(PROTOCOL_BINARY_CMD_DELETE));
498    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
499              validate(PROTOCOL_BINARY_CMD_DELETEQ));
500}
501
502TEST_F(DeleteValidatorTest, WithValue) {
503    request.message.header.request.bodylen = htonl(20);
504    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
505              validate(PROTOCOL_BINARY_CMD_DELETE));
506    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
507              validate(PROTOCOL_BINARY_CMD_DELETEQ));
508}
509
510TEST_F(DeleteValidatorTest, InvalidMagic) {
511    request.message.header.request.magic = 0;
512    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
513              validate(PROTOCOL_BINARY_CMD_DELETE));
514    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
515              validate(PROTOCOL_BINARY_CMD_DELETEQ));
516}
517
518TEST_F(DeleteValidatorTest, InvalidExtlen) {
519    request.message.header.request.extlen = 21;
520    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
521              validate(PROTOCOL_BINARY_CMD_DELETE));
522    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
523              validate(PROTOCOL_BINARY_CMD_DELETEQ));
524}
525
526TEST_F(DeleteValidatorTest, NoKey) {
527    request.message.header.request.keylen = 0;
528    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
529              validate(PROTOCOL_BINARY_CMD_DELETE));
530    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
531              validate(PROTOCOL_BINARY_CMD_DELETEQ));
532}
533
534TEST_F(DeleteValidatorTest, InvalidDatatype) {
535    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
536    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
537              validate(PROTOCOL_BINARY_CMD_DELETE));
538    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
539              validate(PROTOCOL_BINARY_CMD_DELETEQ));
540}
541
542// Test INCREMENT[q] and DECREMENT[q]
543class IncrementDecrementValidatorTest : public ValidatorTest {
544    void SetUp() override {
545        ValidatorTest::SetUp();
546        request.message.header.request.extlen = 20;
547        request.message.header.request.keylen = htons(10);
548        request.message.header.request.bodylen = htonl(30);
549    }
550
551protected:
552    int validate(protocol_binary_command opcode) {
553        return ValidatorTest::validate(opcode, static_cast<void*>(&request));
554    }
555};
556
557TEST_F(IncrementDecrementValidatorTest, CorrectMessage) {
558    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
559              validate(PROTOCOL_BINARY_CMD_INCREMENT));
560    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
561              validate(PROTOCOL_BINARY_CMD_INCREMENTQ));
562    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
563              validate(PROTOCOL_BINARY_CMD_DECREMENT));
564    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
565              validate(PROTOCOL_BINARY_CMD_DECREMENTQ));
566}
567
568TEST_F(IncrementDecrementValidatorTest, Cas) {
569    request.message.header.request.cas = 1;
570    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
571              validate(PROTOCOL_BINARY_CMD_INCREMENT));
572    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
573              validate(PROTOCOL_BINARY_CMD_INCREMENTQ));
574    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
575              validate(PROTOCOL_BINARY_CMD_DECREMENT));
576    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
577              validate(PROTOCOL_BINARY_CMD_DECREMENTQ));
578}
579
580TEST_F(IncrementDecrementValidatorTest, InvalidMagic) {
581    request.message.header.request.magic = 0;
582    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
583              validate(PROTOCOL_BINARY_CMD_INCREMENT));
584    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
585              validate(PROTOCOL_BINARY_CMD_INCREMENTQ));
586    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
587              validate(PROTOCOL_BINARY_CMD_DECREMENT));
588    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
589              validate(PROTOCOL_BINARY_CMD_DECREMENTQ));
590}
591
592TEST_F(IncrementDecrementValidatorTest, InvalidExtlen) {
593    request.message.header.request.extlen = 21;
594    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
595              validate(PROTOCOL_BINARY_CMD_INCREMENT));
596    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
597              validate(PROTOCOL_BINARY_CMD_INCREMENTQ));
598    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
599              validate(PROTOCOL_BINARY_CMD_DECREMENT));
600    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
601              validate(PROTOCOL_BINARY_CMD_DECREMENTQ));
602}
603
604TEST_F(IncrementDecrementValidatorTest, NoKey) {
605    request.message.header.request.keylen = 0;
606    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
607              validate(PROTOCOL_BINARY_CMD_INCREMENT));
608    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
609              validate(PROTOCOL_BINARY_CMD_INCREMENTQ));
610    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
611              validate(PROTOCOL_BINARY_CMD_DECREMENT));
612    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
613              validate(PROTOCOL_BINARY_CMD_DECREMENTQ));
614}
615
616TEST_F(IncrementDecrementValidatorTest, WithValue) {
617    request.message.header.request.bodylen = htonl(40);
618    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
619              validate(PROTOCOL_BINARY_CMD_INCREMENT));
620    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
621              validate(PROTOCOL_BINARY_CMD_INCREMENTQ));
622    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
623              validate(PROTOCOL_BINARY_CMD_DECREMENT));
624    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
625              validate(PROTOCOL_BINARY_CMD_DECREMENTQ));
626}
627
628TEST_F(IncrementDecrementValidatorTest, InvalidDatatype) {
629    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
630    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
631              validate(PROTOCOL_BINARY_CMD_INCREMENT));
632    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
633              validate(PROTOCOL_BINARY_CMD_INCREMENTQ));
634    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
635              validate(PROTOCOL_BINARY_CMD_DECREMENT));
636    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
637              validate(PROTOCOL_BINARY_CMD_DECREMENTQ));
638}
639
640// Test QUIT & QUITQ
641class QuitValidatorTest : public ValidatorTest {
642protected:
643    int validate(protocol_binary_command opcode) {
644        return ValidatorTest::validate(opcode, static_cast<void*>(&request));
645    }
646};
647
648TEST_F(QuitValidatorTest, CorrectMessage) {
649    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
650              validate(PROTOCOL_BINARY_CMD_QUIT));
651    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
652              validate(PROTOCOL_BINARY_CMD_QUITQ));
653}
654
655TEST_F(QuitValidatorTest, InvalidMagic) {
656    request.message.header.request.magic = 0;
657    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
658              validate(PROTOCOL_BINARY_CMD_QUIT));
659    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
660              validate(PROTOCOL_BINARY_CMD_QUITQ));
661}
662
663TEST_F(QuitValidatorTest, InvalidExtlen) {
664    request.message.header.request.extlen = 21;
665    request.message.header.request.bodylen = htonl(21);
666    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
667              validate(PROTOCOL_BINARY_CMD_QUIT));
668    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
669              validate(PROTOCOL_BINARY_CMD_QUITQ));
670}
671
672TEST_F(QuitValidatorTest, InvalidKey) {
673    request.message.header.request.keylen = 10;
674    request.message.header.request.bodylen = ntohl(10);
675    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
676              validate(PROTOCOL_BINARY_CMD_QUIT));
677    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
678              validate(PROTOCOL_BINARY_CMD_QUITQ));
679}
680
681TEST_F(QuitValidatorTest, InvalidCas) {
682    request.message.header.request.cas = 1;
683    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
684              validate(PROTOCOL_BINARY_CMD_QUIT));
685    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
686              validate(PROTOCOL_BINARY_CMD_QUITQ));
687}
688
689TEST_F(QuitValidatorTest, InvalidBodylen) {
690    request.message.header.request.bodylen = htonl(10);
691    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
692              validate(PROTOCOL_BINARY_CMD_QUIT));
693    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
694              validate(PROTOCOL_BINARY_CMD_QUITQ));
695}
696
697TEST_F(QuitValidatorTest, InvalidDatatype) {
698    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
699    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
700              validate(PROTOCOL_BINARY_CMD_QUIT));
701    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
702              validate(PROTOCOL_BINARY_CMD_QUITQ));
703}
704
705// Test FLUSH & FLUSHQ
706class FlushValidatorTest : public ValidatorTest {
707protected:
708    int validate(protocol_binary_command opcode) {
709        return ValidatorTest::validate(opcode, static_cast<void*>(&request));
710    }
711};
712
713TEST_F(FlushValidatorTest, CorrectMessage) {
714    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
715              validate(PROTOCOL_BINARY_CMD_FLUSH));
716    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
717              validate(PROTOCOL_BINARY_CMD_FLUSHQ));
718}
719
720TEST_F(FlushValidatorTest, CorrectMessageWithTime) {
721    request.message.header.request.extlen = 4;
722    request.message.header.request.bodylen = htonl(4);
723    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
724              validate(PROTOCOL_BINARY_CMD_FLUSH));
725    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
726              validate(PROTOCOL_BINARY_CMD_FLUSHQ));
727}
728
729TEST_F(FlushValidatorTest, CorrectMessageWithUnsupportedTime) {
730    request.message.header.request.extlen = 4;
731    request.message.header.request.bodylen = htonl(4);
732    *reinterpret_cast<uint32_t*>(request.bytes + sizeof(request.bytes)) = 1;
733    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED,
734              validate(PROTOCOL_BINARY_CMD_FLUSH));
735    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED,
736              validate(PROTOCOL_BINARY_CMD_FLUSHQ));
737}
738
739TEST_F(FlushValidatorTest, InvalidMagic) {
740    request.message.header.request.magic = 0;
741    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
742              validate(PROTOCOL_BINARY_CMD_FLUSH));
743    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
744              validate(PROTOCOL_BINARY_CMD_FLUSHQ));
745}
746
747TEST_F(FlushValidatorTest, InvalidExtlen) {
748    request.message.header.request.extlen = 21;
749    request.message.header.request.bodylen = htonl(21);
750    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
751              validate(PROTOCOL_BINARY_CMD_FLUSH));
752    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
753              validate(PROTOCOL_BINARY_CMD_FLUSHQ));
754}
755
756TEST_F(FlushValidatorTest, InvalidKey) {
757    request.message.header.request.keylen = 10;
758    request.message.header.request.bodylen = ntohl(10);
759    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
760              validate(PROTOCOL_BINARY_CMD_FLUSH));
761    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
762              validate(PROTOCOL_BINARY_CMD_FLUSHQ));
763}
764
765TEST_F(FlushValidatorTest, InvalidCas) {
766    request.message.header.request.cas = 1;
767    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
768              validate(PROTOCOL_BINARY_CMD_FLUSH));
769    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
770              validate(PROTOCOL_BINARY_CMD_FLUSHQ));
771}
772
773TEST_F(FlushValidatorTest, InvalidBodylen) {
774    request.message.header.request.bodylen = htonl(10);
775    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
776              validate(PROTOCOL_BINARY_CMD_FLUSH));
777    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
778              validate(PROTOCOL_BINARY_CMD_FLUSHQ));
779}
780
781TEST_F(FlushValidatorTest, InvalidDatatype) {
782    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
783    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
784              validate(PROTOCOL_BINARY_CMD_FLUSH));
785    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
786              validate(PROTOCOL_BINARY_CMD_FLUSHQ));
787}
788
789// test Noop
790class NoopValidatorTest : public ValidatorTest {
791protected:
792    protocol_binary_response_status validate() {
793        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_NOOP,
794                                       static_cast<void*>(&request));
795    }
796};
797
798TEST_F(NoopValidatorTest, CorrectMessage) {
799    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
800}
801
802TEST_F(NoopValidatorTest, InvalidMagic) {
803    request.message.header.request.magic = 0;
804    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
805}
806
807TEST_F(NoopValidatorTest, InvalidExtlen) {
808    request.message.header.request.extlen = 21;
809    request.message.header.request.bodylen = htonl(21);
810    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
811}
812
813TEST_F(NoopValidatorTest, InvalidKeylen) {
814    request.message.header.request.keylen = ntohs(32);
815    request.message.header.request.bodylen = htonl(32);
816    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
817}
818
819TEST_F(NoopValidatorTest, InvalidBodylen) {
820    request.message.header.request.bodylen = htonl(100);
821    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
822}
823
824TEST_F(NoopValidatorTest, InvalidDatatype) {
825    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
826    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
827}
828
829TEST_F(NoopValidatorTest, InvalidCas) {
830    request.message.header.request.cas = 1;
831    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
832}
833
834// test version
835class VersionValidatorTest : public ValidatorTest {
836protected:
837    protocol_binary_response_status validate() {
838        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_VERSION,
839                                       static_cast<void*>(&request));
840    }
841};
842
843TEST_F(VersionValidatorTest, CorrectMessage) {
844    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
845}
846
847TEST_F(VersionValidatorTest, InvalidMagic) {
848    request.message.header.request.magic = 0;
849    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
850}
851
852TEST_F(VersionValidatorTest, InvalidExtlen) {
853    request.message.header.request.extlen = 21;
854    request.message.header.request.bodylen = htonl(21);
855    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
856}
857
858TEST_F(VersionValidatorTest, InvalidKeylen) {
859    request.message.header.request.keylen = ntohs(32);
860    request.message.header.request.bodylen = htonl(32);
861    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
862}
863
864TEST_F(VersionValidatorTest, InvalidBodylen) {
865    request.message.header.request.bodylen = htonl(100);
866    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
867}
868
869TEST_F(VersionValidatorTest, InvalidDatatype) {
870    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
871    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
872}
873
874TEST_F(VersionValidatorTest, InvalidCas) {
875    request.message.header.request.cas = 1;
876    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
877}
878
879// test stat
880class StatValidatorTest : public ValidatorTest {
881protected:
882    protocol_binary_response_status validate() {
883        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_STAT,
884                                       static_cast<void*>(&request));
885    }
886};
887
888TEST_F(StatValidatorTest, CorrectMessage) {
889    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
890}
891
892TEST_F(StatValidatorTest, WithKey) {
893    request.message.header.request.keylen = htons(21);
894    request.message.header.request.bodylen = htonl(21);
895    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
896}
897
898TEST_F(StatValidatorTest, InvalidMagic) {
899    request.message.header.request.magic = 0;
900    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
901}
902
903TEST_F(StatValidatorTest, InvalidExtlen) {
904    request.message.header.request.extlen = 21;
905    request.message.header.request.bodylen = htonl(21);
906    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
907}
908
909TEST_F(StatValidatorTest, InvalidBodylen) {
910    request.message.header.request.bodylen = htonl(100);
911    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
912}
913
914TEST_F(StatValidatorTest, InvalidDatatype) {
915    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
916    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
917}
918
919TEST_F(StatValidatorTest, InvalidCas) {
920    request.message.header.request.cas = 1;
921    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
922}
923
924// test verbosity
925class VerbosityValidatorTest : public ValidatorTest {
926    void SetUp() override {
927        ValidatorTest::SetUp();
928        request.message.header.request.extlen = 4;
929        request.message.header.request.bodylen = htonl(4);
930    }
931
932protected:
933    protocol_binary_response_status validate() {
934        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_VERBOSITY,
935                                       static_cast<void*>(&request));
936    }
937};
938
939TEST_F(VerbosityValidatorTest, CorrectMessage) {
940    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
941}
942
943TEST_F(VerbosityValidatorTest, InvalidMagic) {
944    request.message.header.request.magic = 0;
945    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
946}
947
948TEST_F(VerbosityValidatorTest, InvalidExtlen) {
949    request.message.header.request.extlen = 21;
950    request.message.header.request.bodylen = htonl(21);
951    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
952}
953
954TEST_F(VerbosityValidatorTest, InvalidBodylen) {
955    request.message.header.request.bodylen = htonl(100);
956    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
957}
958
959TEST_F(VerbosityValidatorTest, InvalidDatatype) {
960    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
961    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
962}
963
964TEST_F(VerbosityValidatorTest, InvalidKey) {
965    request.message.header.request.keylen = htons(21);
966    request.message.header.request.bodylen = htonl(21);
967    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
968}
969
970TEST_F(VerbosityValidatorTest, InvalidCas) {
971    request.message.header.request.cas = 1;
972    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
973}
974
975// test HELLO
976class HelloValidatorTest : public ValidatorTest {
977protected:
978    protocol_binary_response_status validate() {
979        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_HELLO,
980                                       static_cast<void*>(&request));
981    }
982};
983
984TEST_F(HelloValidatorTest, CorrectMessage) {
985    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
986}
987
988TEST_F(HelloValidatorTest, MultipleFeatures) {
989    request.message.header.request.bodylen = htonl(2);
990    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
991    request.message.header.request.bodylen = htonl(4);
992    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
993    request.message.header.request.bodylen = htonl(6);
994    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
995}
996
997TEST_F(HelloValidatorTest, WithKey) {
998    request.message.header.request.keylen = htons(21);
999    request.message.header.request.bodylen = htonl(21);
1000    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
1001}
1002
1003TEST_F(HelloValidatorTest, InvalidMagic) {
1004    request.message.header.request.magic = 0;
1005    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1006}
1007
1008TEST_F(HelloValidatorTest, InvalidExtlen) {
1009    request.message.header.request.extlen = 2;
1010    request.message.header.request.bodylen = htonl(2);
1011    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1012}
1013
1014TEST_F(HelloValidatorTest, InvalidBodylen) {
1015    request.message.header.request.bodylen = htonl(1);
1016    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1017}
1018
1019TEST_F(HelloValidatorTest, InvalidDatatype) {
1020    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
1021    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1022}
1023
1024TEST_F(HelloValidatorTest, InvalidCas) {
1025    request.message.header.request.cas = 1;
1026    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1027}
1028
1029// test SASL_LIST_MECHS
1030class SaslListMechValidatorTest : public ValidatorTest {
1031protected:
1032    protocol_binary_response_status validate() {
1033        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_SASL_LIST_MECHS,
1034                                       static_cast<void*>(&request));
1035    }
1036};
1037
1038TEST_F(SaslListMechValidatorTest, CorrectMessage) {
1039    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
1040}
1041
1042TEST_F(SaslListMechValidatorTest, InvalidMagic) {
1043    request.message.header.request.magic = 0;
1044    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1045}
1046
1047TEST_F(SaslListMechValidatorTest, InvalidExtlen) {
1048    request.message.header.request.extlen = 2;
1049    request.message.header.request.bodylen = htonl(2);
1050    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1051}
1052
1053TEST_F(SaslListMechValidatorTest, InvalidKey) {
1054    request.message.header.request.keylen = htons(21);
1055    request.message.header.request.bodylen = htonl(21);
1056    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1057}
1058
1059TEST_F(SaslListMechValidatorTest, InvalidBodylen) {
1060    request.message.header.request.bodylen = htonl(1);
1061    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1062}
1063
1064TEST_F(SaslListMechValidatorTest, InvalidDatatype) {
1065    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
1066    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1067}
1068
1069TEST_F(SaslListMechValidatorTest, InvalidCas) {
1070    request.message.header.request.cas = 1;
1071    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1072}
1073
1074// test SASL_AUTH
1075class SaslAuthValidatorTest : public ValidatorTest {
1076    void SetUp() override {
1077        ValidatorTest::SetUp();
1078        request.message.header.request.keylen = htons(10);
1079        request.message.header.request.bodylen = htonl(10);
1080    }
1081
1082protected:
1083    int validate(protocol_binary_command opcode) {
1084        return ValidatorTest::validate(opcode, static_cast<void*>(&request));
1085    }
1086};
1087
1088TEST_F(SaslAuthValidatorTest, CorrectMessage) {
1089    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
1090              validate(PROTOCOL_BINARY_CMD_SASL_AUTH));
1091    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
1092              validate(PROTOCOL_BINARY_CMD_SASL_STEP));
1093}
1094
1095TEST_F(SaslAuthValidatorTest, WithChallenge) {
1096    request.message.header.request.bodylen = htonl(20);
1097    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
1098              validate(PROTOCOL_BINARY_CMD_SASL_AUTH));
1099    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS,
1100              validate(PROTOCOL_BINARY_CMD_SASL_STEP));
1101}
1102
1103TEST_F(SaslAuthValidatorTest, InvalidMagic) {
1104    request.message.header.request.magic = 0;
1105    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
1106              validate(PROTOCOL_BINARY_CMD_SASL_AUTH));
1107    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
1108              validate(PROTOCOL_BINARY_CMD_SASL_STEP));
1109}
1110
1111TEST_F(SaslAuthValidatorTest, InvalidExtlen) {
1112    request.message.header.request.extlen = 2;
1113    request.message.header.request.bodylen = htonl(2);
1114    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
1115              validate(PROTOCOL_BINARY_CMD_SASL_AUTH));
1116    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
1117              validate(PROTOCOL_BINARY_CMD_SASL_STEP));
1118}
1119
1120TEST_F(SaslAuthValidatorTest, InvalidKey) {
1121    request.message.header.request.keylen = 0;
1122    request.message.header.request.bodylen = 0;
1123    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
1124              validate(PROTOCOL_BINARY_CMD_SASL_AUTH));
1125    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
1126              validate(PROTOCOL_BINARY_CMD_SASL_STEP));
1127}
1128
1129TEST_F(SaslAuthValidatorTest, InvalidDatatype) {
1130    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
1131    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
1132              validate(PROTOCOL_BINARY_CMD_SASL_AUTH));
1133    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
1134              validate(PROTOCOL_BINARY_CMD_SASL_STEP));
1135}
1136
1137TEST_F(SaslAuthValidatorTest, InvalidCas) {
1138    request.message.header.request.cas = 1;
1139    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
1140              validate(PROTOCOL_BINARY_CMD_SASL_AUTH));
1141    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL,
1142              validate(PROTOCOL_BINARY_CMD_SASL_STEP));
1143}
1144
1145class GetErrmapValidatorTest : public ValidatorTest {
1146protected:
1147    protocol_binary_response_status validate() {
1148        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_GET_ERROR_MAP,
1149                                       static_cast<void*>(&request));
1150    }
1151};
1152
1153TEST_F(GetErrmapValidatorTest, CorrectMessage) {
1154    request.message.header.request.bodylen = htonl(2);
1155    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
1156}
1157
1158TEST_F(GetErrmapValidatorTest, InvalidMagic) {
1159    request.message.header.request.magic = 0;
1160    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1161}
1162
1163TEST_F(GetErrmapValidatorTest, MissingBody) {
1164    request.message.header.request.bodylen = 0;
1165    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1166}
1167
1168// test IOCTL_GET
1169class IoctlGetValidatorTest : public ValidatorTest {
1170    void SetUp() override {
1171        ValidatorTest::SetUp();
1172        request.message.header.request.keylen = htons(10);
1173        request.message.header.request.bodylen = htonl(10);
1174    }
1175
1176protected:
1177    // #defined in memcached.h..
1178    const int IOCTL_KEY_LENGTH = 128;
1179
1180    protocol_binary_response_status validate() {
1181        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_IOCTL_GET,
1182                                       static_cast<void*>(&request));
1183    }
1184};
1185
1186TEST_F(IoctlGetValidatorTest, CorrectMessage) {
1187    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
1188}
1189
1190TEST_F(IoctlGetValidatorTest, InvalidMagic) {
1191    request.message.header.request.magic = 0;
1192    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1193}
1194
1195TEST_F(IoctlGetValidatorTest, InvalidExtlen) {
1196    request.message.header.request.extlen = 2;
1197    request.message.header.request.bodylen = htonl(12);
1198    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1199}
1200
1201TEST_F(IoctlGetValidatorTest, InvalidKey) {
1202    request.message.header.request.keylen = 0;
1203    request.message.header.request.bodylen = 0;
1204    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1205    request.message.header.request.keylen = htons(IOCTL_KEY_LENGTH + 1);
1206    request.message.header.request.bodylen = htonl(IOCTL_KEY_LENGTH + 1);
1207    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1208}
1209
1210TEST_F(IoctlGetValidatorTest, InvalidDatatype) {
1211    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
1212    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1213}
1214
1215TEST_F(IoctlGetValidatorTest, InvalidCas) {
1216    request.message.header.request.cas = 1;
1217    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1218}
1219
1220TEST_F(IoctlGetValidatorTest, InvalidBody) {
1221    request.message.header.request.bodylen = htonl(20);
1222    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1223}
1224
1225// test IOCTL_SET
1226class IoctlSetValidatorTest : public ValidatorTest {
1227    void SetUp() override {
1228        ValidatorTest::SetUp();
1229        request.message.header.request.keylen = htons(10);
1230        request.message.header.request.bodylen = htonl(10);
1231    }
1232
1233protected:
1234    // #defined in memcached.h..
1235    const int IOCTL_KEY_LENGTH = 128;
1236    const int IOCTL_VAL_LENGTH = 128;
1237
1238    protocol_binary_response_status validate() {
1239        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_IOCTL_SET,
1240                                       static_cast<void*>(&request));
1241    }
1242};
1243
1244TEST_F(IoctlSetValidatorTest, CorrectMessage) {
1245    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
1246}
1247
1248TEST_F(IoctlSetValidatorTest, InvalidMagic) {
1249    request.message.header.request.magic = 0;
1250    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1251}
1252
1253TEST_F(IoctlSetValidatorTest, InvalidExtlen) {
1254    request.message.header.request.extlen = 2;
1255    request.message.header.request.bodylen = htonl(12);
1256    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1257}
1258
1259TEST_F(IoctlSetValidatorTest, InvalidKey) {
1260    request.message.header.request.keylen = 0;
1261    request.message.header.request.bodylen = 0;
1262    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1263    request.message.header.request.keylen = htons(IOCTL_KEY_LENGTH + 1);
1264    request.message.header.request.bodylen = htonl(IOCTL_KEY_LENGTH + 1);
1265    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1266}
1267
1268TEST_F(IoctlSetValidatorTest, InvalidDatatype) {
1269    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
1270    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1271}
1272
1273TEST_F(IoctlSetValidatorTest, InvalidCas) {
1274    request.message.header.request.cas = 1;
1275    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1276}
1277
1278TEST_F(IoctlSetValidatorTest, InvalidBody) {
1279    request.message.header.request.bodylen = htonl(IOCTL_VAL_LENGTH + 11);
1280    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1281}
1282
1283TEST_F(IoctlSetValidatorTest, ValidBody) {
1284    request.message.header.request.bodylen = htonl(IOCTL_VAL_LENGTH + 10);
1285    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
1286}
1287
1288// test AUDIT_PUT
1289class AuditPutValidatorTest : public ValidatorTest {
1290    void SetUp() override {
1291        ValidatorTest::SetUp();
1292        request.message.header.request.extlen = 4;
1293        request.message.header.request.bodylen = htonl(10);
1294    }
1295
1296protected:
1297    protocol_binary_response_status validate() {
1298        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_AUDIT_PUT,
1299                                       static_cast<void*>(&request));
1300    }
1301};
1302
1303TEST_F(AuditPutValidatorTest, CorrectMessage) {
1304    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
1305}
1306
1307TEST_F(AuditPutValidatorTest, InvalidMagic) {
1308    request.message.header.request.magic = 0;
1309    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1310}
1311
1312TEST_F(AuditPutValidatorTest, InvalidExtlen) {
1313    request.message.header.request.extlen = 2;
1314    request.message.header.request.bodylen = htonl(12);
1315    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1316}
1317
1318TEST_F(AuditPutValidatorTest, InvalidKey) {
1319    request.message.header.request.keylen = 10;
1320    request.message.header.request.bodylen = htonl(15);
1321    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1322}
1323
1324TEST_F(AuditPutValidatorTest, InvalidDatatype) {
1325    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
1326    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1327}
1328
1329TEST_F(AuditPutValidatorTest, InvalidCas) {
1330    request.message.header.request.cas = 1;
1331    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1332}
1333
1334TEST_F(AuditPutValidatorTest, InvalidBody) {
1335    request.message.header.request.bodylen = htonl(4);
1336    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1337}
1338
1339// Test audit_config_reload
1340class AuditConfigReloadValidatorTest : public ValidatorTest {
1341protected:
1342    protocol_binary_response_status validate() {
1343        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_AUDIT_CONFIG_RELOAD,
1344                                       static_cast<void*>(&request));
1345    }
1346};
1347
1348TEST_F(AuditConfigReloadValidatorTest, CorrectMessage) {
1349    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
1350}
1351
1352TEST_F(AuditConfigReloadValidatorTest, InvalidMagic) {
1353    request.message.header.request.magic = 0;
1354    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1355}
1356
1357TEST_F(AuditConfigReloadValidatorTest, InvalidExtlen) {
1358    request.message.header.request.extlen = 2;
1359    request.message.header.request.bodylen = htonl(2);
1360    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1361}
1362
1363TEST_F(AuditConfigReloadValidatorTest, InvalidKey) {
1364    request.message.header.request.keylen = 10;
1365    request.message.header.request.bodylen = htonl(10);
1366    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1367}
1368
1369TEST_F(AuditConfigReloadValidatorTest, InvalidDatatype) {
1370    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
1371    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1372}
1373
1374TEST_F(AuditConfigReloadValidatorTest, InvalidCas) {
1375    request.message.header.request.cas = 1;
1376    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1377}
1378
1379TEST_F(AuditConfigReloadValidatorTest, InvalidBody) {
1380    request.message.header.request.bodylen = htonl(4);
1381    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1382}
1383
1384// Test shutdown
1385class ShutdownValidatorTest : public ValidatorTest {
1386    void SetUp() override {
1387        ValidatorTest::SetUp();
1388        request.message.header.request.cas = 1;
1389    }
1390
1391protected:
1392    protocol_binary_response_status validate() {
1393        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_SHUTDOWN,
1394                                       static_cast<void*>(&request));
1395    }
1396};
1397
1398TEST_F(ShutdownValidatorTest, CorrectMessage) {
1399    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
1400}
1401
1402TEST_F(ShutdownValidatorTest, InvalidMagic) {
1403    request.message.header.request.magic = 0;
1404    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1405}
1406
1407TEST_F(ShutdownValidatorTest, InvalidExtlen) {
1408    request.message.header.request.extlen = 2;
1409    request.message.header.request.bodylen = htonl(2);
1410    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1411}
1412
1413TEST_F(ShutdownValidatorTest, InvalidKey) {
1414    request.message.header.request.keylen = 10;
1415    request.message.header.request.bodylen = htonl(10);
1416    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1417}
1418
1419TEST_F(ShutdownValidatorTest, InvalidDatatype) {
1420    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
1421    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1422}
1423
1424TEST_F(ShutdownValidatorTest, InvalidCas) {
1425    request.message.header.request.cas = 0;
1426    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1427}
1428
1429TEST_F(ShutdownValidatorTest, InvalidBody) {
1430    request.message.header.request.bodylen = htonl(4);
1431    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1432}
1433
1434class DcpOpenValidatorTest : public ValidatorTest {
1435    void SetUp() override {
1436        ValidatorTest::SetUp();
1437        memset(&request, 0, sizeof(request));
1438        request.message.header.request.magic = PROTOCOL_BINARY_REQ;
1439        request.message.header.request.extlen = 8;
1440        request.message.header.request.keylen = htons(2);
1441        request.message.header.request.bodylen = htonl(10);
1442        request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
1443    }
1444
1445protected:
1446    protocol_binary_response_status validate() {
1447        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_DCP_OPEN,
1448                                       static_cast<void*>(&request));
1449    }
1450
1451    protocol_binary_request_dcp_open &request = *reinterpret_cast<protocol_binary_request_dcp_open*>(blob);
1452};
1453
1454TEST_F(DcpOpenValidatorTest, CorrectMessage) {
1455    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
1456}
1457
1458TEST_F(DcpOpenValidatorTest, InvalidMagic) {
1459    request.message.header.request.magic = 0;
1460    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1461}
1462
1463TEST_F(DcpOpenValidatorTest, InvalidExtlen) {
1464    request.message.header.request.extlen = 9;
1465    request.message.header.request.bodylen = htonl(11);
1466    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1467}
1468
1469TEST_F(DcpOpenValidatorTest, InvalidKeylen) {
1470    request.message.header.request.keylen = 0;
1471    request.message.header.request.bodylen = htonl(8);
1472    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1473}
1474
1475TEST_F(DcpOpenValidatorTest, InvalidDatatype) {
1476    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
1477    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1478}
1479
1480TEST_F(DcpOpenValidatorTest, ValueButNoCollections) {
1481    request.message.header.request.bodylen = htonl(10 + 20);
1482    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1483}
1484
1485TEST_F(DcpOpenValidatorTest, CorrectMessageValueCollections) {
1486    request.message.header.request.bodylen = htonl(10 + 20);
1487    request.message.body.flags = ntohl(DCP_OPEN_COLLECTIONS);
1488    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
1489}
1490
1491class DcpAddStreamValidatorTest : public ValidatorTest {
1492    void SetUp() override {
1493        ValidatorTest::SetUp();
1494        request.message.header.request.extlen = 4;
1495        request.message.header.request.bodylen = htonl(4);
1496    }
1497
1498protected:
1499    protocol_binary_response_status validate() {
1500        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_DCP_ADD_STREAM,
1501                                       static_cast<void*>(&request));
1502    }
1503};
1504
1505TEST_F(DcpAddStreamValidatorTest, CorrectMessage) {
1506    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
1507}
1508
1509TEST_F(DcpAddStreamValidatorTest, InvalidMagic) {
1510    request.message.header.request.magic = 0;
1511    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1512}
1513
1514TEST_F(DcpAddStreamValidatorTest, InvalidExtlen) {
1515    request.message.header.request.extlen = 5;
1516    request.message.header.request.bodylen = htonl(5);
1517    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1518}
1519
1520TEST_F(DcpAddStreamValidatorTest, InvalidKeylen) {
1521    request.message.header.request.keylen = 4;
1522    request.message.header.request.bodylen = htonl(8);
1523    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1524}
1525
1526TEST_F(DcpAddStreamValidatorTest, InvalidDatatype) {
1527    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
1528    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1529}
1530
1531TEST_F(DcpAddStreamValidatorTest, InvalidBody) {
1532    request.message.header.request.bodylen = htonl(12);
1533    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1534}
1535
1536class DcpCloseStreamValidatorTest : public ValidatorTest {
1537protected:
1538    protocol_binary_response_status validate() {
1539        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_DCP_CLOSE_STREAM,
1540                                       static_cast<void*>(&request));
1541    }
1542};
1543
1544TEST_F(DcpCloseStreamValidatorTest, CorrectMessage) {
1545    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
1546}
1547
1548TEST_F(DcpCloseStreamValidatorTest, InvalidMagic) {
1549    request.message.header.request.magic = 0;
1550    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1551}
1552
1553TEST_F(DcpCloseStreamValidatorTest, InvalidExtlen) {
1554    request.message.header.request.extlen = 5;
1555    request.message.header.request.bodylen = htonl(5);
1556    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1557}
1558
1559TEST_F(DcpCloseStreamValidatorTest, InvalidKeylen) {
1560    request.message.header.request.keylen = 4;
1561    request.message.header.request.bodylen = htonl(4);
1562    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1563}
1564
1565TEST_F(DcpCloseStreamValidatorTest, InvalidDatatype) {
1566    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
1567    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1568}
1569
1570TEST_F(DcpCloseStreamValidatorTest, InvalidBody) {
1571    request.message.header.request.bodylen = htonl(12);
1572    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1573}
1574
1575class DcpGetFailoverLogValidatorTest : public ValidatorTest {
1576protected:
1577    protocol_binary_response_status validate() {
1578        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_DCP_GET_FAILOVER_LOG,
1579                                       static_cast<void*>(&request));
1580    }
1581};
1582
1583TEST_F(DcpGetFailoverLogValidatorTest, CorrectMessage) {
1584    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
1585}
1586
1587TEST_F(DcpGetFailoverLogValidatorTest, InvalidMagic) {
1588    request.message.header.request.magic = 0;
1589    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1590}
1591
1592TEST_F(DcpGetFailoverLogValidatorTest, InvalidExtlen) {
1593    request.message.header.request.extlen = 5;
1594    request.message.header.request.bodylen = htonl(5);
1595    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1596}
1597
1598TEST_F(DcpGetFailoverLogValidatorTest, InvalidKeylen) {
1599    request.message.header.request.keylen = 4;
1600    request.message.header.request.bodylen = htonl(4);
1601    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1602}
1603
1604TEST_F(DcpGetFailoverLogValidatorTest, InvalidDatatype) {
1605    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
1606    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1607}
1608
1609TEST_F(DcpGetFailoverLogValidatorTest, InvalidBody) {
1610    request.message.header.request.bodylen = htonl(12);
1611    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1612}
1613
1614class DcpStreamReqValidatorTest : public ValidatorTest {
1615    void SetUp() override {
1616        ValidatorTest::SetUp();
1617        request.message.header.request.extlen = 48;
1618        request.message.header.request.bodylen = htonl(48);
1619    }
1620
1621protected:
1622    protocol_binary_response_status validate() {
1623        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_DCP_STREAM_REQ,
1624                                       static_cast<void*>(&request));
1625    }
1626};
1627
1628TEST_F(DcpStreamReqValidatorTest, CorrectMessage) {
1629    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
1630}
1631
1632TEST_F(DcpStreamReqValidatorTest, InvalidMagic) {
1633    request.message.header.request.magic = 0;
1634    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1635}
1636
1637TEST_F(DcpStreamReqValidatorTest, InvalidExtlen) {
1638    request.message.header.request.extlen = 5;
1639    request.message.header.request.bodylen = htonl(5);
1640    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1641}
1642
1643TEST_F(DcpStreamReqValidatorTest, InvalidKeylen) {
1644    request.message.header.request.keylen = 4;
1645    request.message.header.request.bodylen = htonl(54);
1646    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1647}
1648
1649TEST_F(DcpStreamReqValidatorTest, InvalidDatatype) {
1650    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
1651    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1652}
1653// Can the stream req also conain data?
1654// TEST_F(DcpStreamReqValidatorTest, InvalidBody) {
1655//     request.message.header.request.bodylen = htonl(12);
1656//     EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1657// }
1658
1659class DcpStreamEndValidatorTest : public ValidatorTest {
1660    void SetUp() override {
1661        ValidatorTest::SetUp();
1662        request.message.header.request.extlen = 4;
1663        request.message.header.request.bodylen = htonl(4);
1664    }
1665
1666protected:
1667    protocol_binary_response_status validate() {
1668        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_DCP_STREAM_END,
1669                                       static_cast<void*>(&request));
1670    }
1671};
1672
1673TEST_F(DcpStreamEndValidatorTest, CorrectMessage) {
1674    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
1675}
1676
1677TEST_F(DcpStreamEndValidatorTest, InvalidMagic) {
1678    request.message.header.request.magic = 0;
1679    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1680}
1681
1682TEST_F(DcpStreamEndValidatorTest, InvalidExtlen) {
1683    request.message.header.request.extlen = 5;
1684    request.message.header.request.bodylen = htonl(5);
1685    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1686}
1687
1688TEST_F(DcpStreamEndValidatorTest, InvalidKeylen) {
1689    request.message.header.request.keylen = 4;
1690    request.message.header.request.bodylen = htonl(8);
1691    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1692}
1693
1694TEST_F(DcpStreamEndValidatorTest, InvalidDatatype) {
1695    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
1696    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1697}
1698
1699TEST_F(DcpStreamEndValidatorTest, InvalidBody) {
1700    request.message.header.request.bodylen = htonl(12);
1701    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1702}
1703
1704class DcpSnapshotMarkerValidatorTest : public ValidatorTest {
1705    void SetUp() override {
1706        ValidatorTest::SetUp();
1707        request.message.header.request.extlen = 20;
1708        request.message.header.request.bodylen = htonl(20);
1709    }
1710
1711protected:
1712    protocol_binary_response_status validate() {
1713        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_DCP_SNAPSHOT_MARKER,
1714                                       static_cast<void*>(&request));
1715    }
1716};
1717
1718TEST_F(DcpSnapshotMarkerValidatorTest, CorrectMessage) {
1719    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
1720}
1721
1722TEST_F(DcpSnapshotMarkerValidatorTest, InvalidMagic) {
1723    request.message.header.request.magic = 0;
1724    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1725}
1726
1727TEST_F(DcpSnapshotMarkerValidatorTest, InvalidExtlen) {
1728    request.message.header.request.extlen = 21;
1729    request.message.header.request.bodylen = htonl(21);
1730    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1731}
1732
1733TEST_F(DcpSnapshotMarkerValidatorTest, InvalidKeylen) {
1734    request.message.header.request.keylen = 32;
1735    request.message.header.request.bodylen = htonl(52);
1736    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1737}
1738
1739TEST_F(DcpSnapshotMarkerValidatorTest, InvalidBodylen) {
1740    request.message.header.request.bodylen = htonl(100);
1741    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1742}
1743
1744TEST_F(DcpSnapshotMarkerValidatorTest, InvalidDatatype) {
1745    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
1746    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1747}
1748
1749/**
1750 * Test class for DcpMutation validation - the bool parameter toggles
1751 * collections on/off (as that subtly changes the encoding of a mutation)
1752 */
1753class DcpMutationValidatorTest : public ValidatorTest,
1754                                 public ::testing::WithParamInterface<bool> {
1755public:
1756    DcpMutationValidatorTest()
1757        : request(GetParam(),
1758                  0 /*opaque*/,
1759                  0 /*vbucket*/,
1760                  0 /*cas*/,
1761                  1 /*keylen*/,
1762                  0 /*valueLen*/,
1763                  PROTOCOL_BINARY_RAW_BYTES,
1764                  0 /*bySeqno*/,
1765                  0 /*revSeqno*/,
1766                  0 /*flags*/,
1767                  0 /*expiration*/,
1768                  0 /*lockTime*/,
1769                  0 /*nmeta*/,
1770                  0 /*nru*/,
1771                  0 /*collectionLen*/) {
1772    }
1773
1774    void SetUp() override {
1775        ValidatorTest::SetUp();
1776        connection.setDcpCollectionAware(GetParam());
1777    }
1778
1779protected:
1780    protocol_binary_response_status validate() {
1781        std::copy(request.bytes, request.bytes + sizeof(request.bytes), blob);
1782        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_DCP_MUTATION,
1783                                       static_cast<void*>(blob));
1784    }
1785
1786    protocol_binary_request_dcp_mutation request;
1787};
1788
1789INSTANTIATE_TEST_CASE_P(CollectionsOnOff,
1790                        DcpMutationValidatorTest,
1791                        ::testing::Bool(),
1792                        ::testing::PrintToStringParamName());
1793
1794TEST_P(DcpMutationValidatorTest, CorrectMessage) {
1795    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
1796}
1797
1798TEST_P(DcpMutationValidatorTest, InvalidMagic) {
1799    request.message.header.request.magic = 0;
1800    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1801}
1802
1803TEST_P(DcpMutationValidatorTest, InvalidExtlen) {
1804    request.message.header.request.extlen = 21;
1805    request.message.header.request.bodylen = htonl(22);
1806    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1807}
1808
1809TEST_P(DcpMutationValidatorTest, InvalidExtlenCollections) {
1810    request.message.header.request.extlen =
1811            protocol_binary_request_dcp_mutation::getExtrasLength(!GetParam());
1812    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1813}
1814
1815TEST_P(DcpMutationValidatorTest, InvalidKeylen) {
1816    request.message.header.request.keylen = 0;
1817    request.message.header.request.bodylen = htonl(31);
1818    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1819}
1820
1821/**
1822 * Test class for DcpDeletion validation - the bool parameter toggles
1823 * collections on/off (as that subtly changes the encoding of a deletion)
1824 */
1825class DcpDeletionValidatorTest : public ValidatorTest,
1826                                 public ::testing::WithParamInterface<bool> {
1827public:
1828    DcpDeletionValidatorTest()
1829        : ValidatorTest(),
1830          request(GetParam() ? makeV2() : makeV1()),
1831          header(request->getHeader()) {
1832        header.request.opcode = (uint8_t)PROTOCOL_BINARY_CMD_DCP_DELETION;
1833    }
1834
1835    void SetUp() override {
1836        ValidatorTest::SetUp();
1837        connection.setDcpCollectionAware(GetParam());
1838    }
1839
1840protected:
1841    protocol_binary_response_status validate() {
1842        std::copy(request->getBytes(),
1843                  request->getBytes() + request->getSizeofBytes(),
1844                  blob);
1845        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_DCP_DELETION,
1846                                       static_cast<void*>(blob));
1847    }
1848
1849    class Request {
1850    public:
1851        virtual protocol_binary_request_header& getHeader() = 0;
1852
1853        virtual uint8_t* getBytes() = 0;
1854
1855        virtual size_t getSizeofBytes() = 0;
1856    };
1857
1858    class RequestV1 : public Request {
1859    public:
1860        RequestV1()
1861            : request(0 /*opaque*/,
1862                      0 /*vbucket*/,
1863                      0 /*cas*/,
1864                      2 /*keylen*/,
1865                      0 /*valueLen*/,
1866                      PROTOCOL_BINARY_RAW_BYTES,
1867                      0 /*bySeqno*/,
1868                      0 /*revSeqno*/,
1869                      0 /*nmeta*/) {
1870        }
1871        protocol_binary_request_header& getHeader() override {
1872            return request.message.header;
1873        }
1874
1875        uint8_t* getBytes() override {
1876            return request.bytes;
1877        }
1878
1879        size_t getSizeofBytes() override {
1880            return sizeof(request.bytes);
1881        }
1882
1883    private:
1884        protocol_binary_request_dcp_deletion request;
1885    };
1886
1887    class RequestV2 : public Request {
1888    public:
1889        RequestV2()
1890            : request(0 /*opaque*/,
1891                      0 /*vbucket*/,
1892                      0 /*cas*/,
1893                      2 /*keylen*/,
1894                      0 /*valueLen*/,
1895                      PROTOCOL_BINARY_RAW_BYTES,
1896                      0 /*bySeqno*/,
1897                      0 /*revSeqno*/,
1898                      0, /*deleteTime*/
1899                      0 /*collectionLen*/) {
1900        }
1901        protocol_binary_request_header& getHeader() override {
1902            return request.message.header;
1903        }
1904
1905        uint8_t* getBytes() override {
1906            return request.bytes;
1907        }
1908
1909        size_t getSizeofBytes() override {
1910            return sizeof(request.bytes);
1911        }
1912
1913    private:
1914        protocol_binary_request_dcp_deletion_v2 request;
1915    };
1916
1917    std::unique_ptr<Request> makeV1() {
1918        return std::make_unique<RequestV1>();
1919    }
1920
1921    std::unique_ptr<Request> makeV2() {
1922        return std::make_unique<RequestV2>();
1923    }
1924
1925    std::unique_ptr<Request> request;
1926    protocol_binary_request_header& header;
1927};
1928
1929INSTANTIATE_TEST_CASE_P(CollectionsOnOff,
1930                        DcpDeletionValidatorTest,
1931                        ::testing::Bool(),
1932                        ::testing::PrintToStringParamName());
1933
1934TEST_P(DcpDeletionValidatorTest, CorrectMessage) {
1935    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
1936}
1937
1938TEST_P(DcpDeletionValidatorTest, InvalidMagic) {
1939    header.request.magic = 0;
1940    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1941}
1942
1943TEST_P(DcpDeletionValidatorTest, ValidDatatype) {
1944    using cb::mcbp::Datatype;
1945    const std::array<uint8_t, 4> datatypes = {
1946            {uint8_t(Datatype::Raw),
1947             uint8_t(Datatype::Raw) | uint8_t(Datatype::Snappy),
1948             uint8_t(Datatype::Xattr),
1949             uint8_t(Datatype::Xattr) | uint8_t(Datatype::Snappy)}};
1950
1951    for (auto valid : datatypes) {
1952        header.request.datatype = valid;
1953        EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate())
1954                    << "Testing valid datatype:" << int(valid);
1955    }
1956}
1957
1958TEST_P(DcpDeletionValidatorTest, InvalidDatatype) {
1959    using cb::mcbp::Datatype;
1960    const std::array<uint8_t, 2> datatypes = {
1961            {uint8_t(Datatype::JSON),
1962             uint8_t(Datatype::Snappy) | uint8_t(Datatype::JSON)}};
1963
1964    for (auto invalid : datatypes) {
1965        header.request.datatype = invalid;
1966        EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate())
1967                    << "Testing invalid datatype:" << int(invalid);
1968    }
1969}
1970
1971TEST_P(DcpDeletionValidatorTest, InvalidExtlen) {
1972    header.request.extlen = 5;
1973    header.request.bodylen = htonl(7);
1974    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1975}
1976
1977TEST_P(DcpDeletionValidatorTest, InvalidExtlenCollections) {
1978    // Flip extlen, so when not collections, set the length collections uses
1979    header.request.extlen =
1980            GetParam() ? protocol_binary_request_dcp_deletion::extlen
1981                       : protocol_binary_request_dcp_deletion_v2::extlen;
1982    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1983}
1984
1985TEST_P(DcpDeletionValidatorTest, InvalidKeylen) {
1986    header.request.keylen = 0;
1987    header.request.bodylen = htonl(18);
1988    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
1989}
1990
1991TEST_P(DcpDeletionValidatorTest, WithValue) {
1992    header.request.bodylen = htonl(100);
1993    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
1994}
1995
1996/**
1997 * Test class for DcpExpiration validation - the bool parameter toggles
1998 * collections on/off (as that subtly changes the encoding of an expiration)
1999 */
2000class DcpExpirationValidatorTest : public ValidatorTest,
2001                                   public ::testing::WithParamInterface<bool> {
2002public:
2003    DcpExpirationValidatorTest()
2004        : ValidatorTest(),
2005          request(GetParam(),
2006                  0 /*opaque*/,
2007                  0 /*vbucket*/,
2008                  0 /*cas*/,
2009                  2 /*keylen*/,
2010                  0 /*valueLen*/,
2011                  PROTOCOL_BINARY_RAW_BYTES,
2012                  0 /*bySeqno*/,
2013                  0 /*revSeqno*/,
2014                  0 /*nmeta*/,
2015                  0 /*collectionLen*/) {
2016        request.message.header.request.opcode =
2017            (uint8_t)PROTOCOL_BINARY_CMD_DCP_EXPIRATION;
2018    }
2019
2020    void SetUp() override {
2021        ValidatorTest::SetUp();
2022        connection.setDcpCollectionAware(GetParam());
2023    }
2024
2025protected:
2026    protocol_binary_response_status validate() {
2027        std::copy(request.bytes, request.bytes + sizeof(request.bytes), blob);
2028        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_DCP_EXPIRATION,
2029                                       static_cast<void*>(blob));
2030    }
2031
2032    protocol_binary_request_dcp_expiration request;
2033};
2034
2035INSTANTIATE_TEST_CASE_P(CollectionsOnOff,
2036                        DcpExpirationValidatorTest,
2037                        ::testing::Bool(),
2038                        ::testing::PrintToStringParamName());
2039
2040TEST_P(DcpExpirationValidatorTest, CorrectMessage) {
2041    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
2042}
2043
2044TEST_P(DcpExpirationValidatorTest, InvalidMagic) {
2045    request.message.header.request.magic = 0;
2046    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2047}
2048
2049TEST_P(DcpExpirationValidatorTest, InvalidExtlen) {
2050    request.message.header.request.extlen = 5;
2051    request.message.header.request.bodylen = htonl(7);
2052    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2053}
2054
2055TEST_P(DcpExpirationValidatorTest, InvalidKeylen) {
2056    request.message.header.request.keylen = 0;
2057    request.message.header.request.bodylen = htonl(18);
2058    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2059}
2060
2061TEST_P(DcpExpirationValidatorTest, InvalidBodylen) {
2062    request.message.header.request.bodylen = htonl(100);
2063    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2064}
2065
2066class DcpFlushValidatorTest : public ValidatorTest {
2067protected:
2068    protocol_binary_response_status validate() {
2069        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_DCP_FLUSH,
2070                                       static_cast<void*>(&request));
2071    }
2072};
2073
2074TEST_F(DcpFlushValidatorTest, CorrectMessage) {
2075    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
2076}
2077
2078TEST_F(DcpFlushValidatorTest, InvalidMagic) {
2079    request.message.header.request.magic = 0;
2080    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2081}
2082
2083TEST_F(DcpFlushValidatorTest, InvalidExtlen) {
2084    request.message.header.request.extlen = 5;
2085    request.message.header.request.bodylen = htonl(5);
2086    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2087}
2088
2089TEST_F(DcpFlushValidatorTest, InvalidKeylen) {
2090    request.message.header.request.keylen = 4;
2091    request.message.header.request.bodylen = htonl(4);
2092    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2093}
2094
2095TEST_F(DcpFlushValidatorTest, InvalidDatatype) {
2096    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2097    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2098}
2099
2100TEST_F(DcpFlushValidatorTest, InvalidBody) {
2101    request.message.header.request.bodylen = htonl(12);
2102    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2103}
2104
2105class DcpSetVbucketStateValidatorTest : public ValidatorTest {
2106    void SetUp() override {
2107        ValidatorTest::SetUp();
2108        memset(&request, 0, sizeof(request));
2109        request.message.header.request.magic = PROTOCOL_BINARY_REQ;
2110        request.message.header.request.extlen = 1;
2111        request.message.header.request.bodylen = htonl(1);
2112        request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
2113        request.message.body.state = 1;
2114    }
2115
2116protected:
2117    protocol_binary_response_status validate() {
2118        return ValidatorTest::validate(
2119            PROTOCOL_BINARY_CMD_DCP_SET_VBUCKET_STATE,
2120            static_cast<void*>(&request));
2121    }
2122
2123    protocol_binary_request_dcp_set_vbucket_state &request =
2124       *reinterpret_cast<protocol_binary_request_dcp_set_vbucket_state*>(blob);
2125};
2126
2127TEST_F(DcpSetVbucketStateValidatorTest, CorrectMessage) {
2128    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
2129}
2130
2131TEST_F(DcpSetVbucketStateValidatorTest, LegalValues) {
2132    for (int ii = 1; ii < 5; ++ii) {
2133        request.message.body.state = ii;
2134        EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
2135    }
2136}
2137
2138TEST_F(DcpSetVbucketStateValidatorTest, InvalidMagic) {
2139    request.message.header.request.magic = 0;
2140    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2141}
2142
2143TEST_F(DcpSetVbucketStateValidatorTest, InvalidExtlen) {
2144    request.message.header.request.extlen = 5;
2145    request.message.header.request.bodylen = htonl(5);
2146    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2147}
2148
2149TEST_F(DcpSetVbucketStateValidatorTest, InvalidKeylen) {
2150    request.message.header.request.keylen = 4;
2151    request.message.header.request.bodylen = htonl(5);
2152    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2153}
2154
2155TEST_F(DcpSetVbucketStateValidatorTest, InvalidDatatype) {
2156    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2157    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2158}
2159
2160TEST_F(DcpSetVbucketStateValidatorTest, InvalidBody) {
2161    request.message.header.request.bodylen = htonl(12);
2162    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2163}
2164
2165TEST_F(DcpSetVbucketStateValidatorTest, IllegalValues) {
2166    request.message.body.state = 5;
2167    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2168    request.message.body.state = 0;
2169    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2170}
2171
2172class DcpNoopValidatorTest : public ValidatorTest {
2173protected:
2174    protocol_binary_response_status validate() {
2175        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_DCP_NOOP,
2176                                       static_cast<void*>(&request));
2177    }
2178};
2179
2180TEST_F(DcpNoopValidatorTest, CorrectMessage) {
2181    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
2182}
2183
2184TEST_F(DcpNoopValidatorTest, InvalidMagic) {
2185    request.message.header.request.magic = 0;
2186    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2187}
2188
2189TEST_F(DcpNoopValidatorTest, InvalidExtlen) {
2190    request.message.header.request.extlen = 5;
2191    request.message.header.request.bodylen = htonl(5);
2192    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2193}
2194
2195TEST_F(DcpNoopValidatorTest, InvalidKeylen) {
2196    request.message.header.request.keylen = 4;
2197    request.message.header.request.bodylen = htonl(4);
2198    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2199}
2200
2201TEST_F(DcpNoopValidatorTest, InvalidDatatype) {
2202    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2203    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2204}
2205
2206TEST_F(DcpNoopValidatorTest, InvalidBody) {
2207    request.message.header.request.bodylen = htonl(12);
2208    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2209}
2210
2211class DcpBufferAckValidatorTest : public ValidatorTest {
2212    void SetUp() override {
2213        ValidatorTest::SetUp();
2214        request.message.header.request.extlen = 4;
2215        request.message.header.request.bodylen = htonl(4);
2216    }
2217
2218protected:
2219    protocol_binary_response_status validate() {
2220        return ValidatorTest::validate(
2221            PROTOCOL_BINARY_CMD_DCP_BUFFER_ACKNOWLEDGEMENT,
2222            static_cast<void*>(&request));
2223    }
2224};
2225
2226TEST_F(DcpBufferAckValidatorTest, CorrectMessage) {
2227    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
2228}
2229
2230TEST_F(DcpBufferAckValidatorTest, InvalidMagic) {
2231    request.message.header.request.magic = 0;
2232    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2233}
2234
2235TEST_F(DcpBufferAckValidatorTest, InvalidExtlen) {
2236    request.message.header.request.extlen = 5;
2237    request.message.header.request.bodylen = htonl(5);
2238    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2239}
2240
2241TEST_F(DcpBufferAckValidatorTest, InvalidKeylen) {
2242    request.message.header.request.keylen = 4;
2243    request.message.header.request.bodylen = htonl(8);
2244    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2245}
2246
2247TEST_F(DcpBufferAckValidatorTest, InvalidDatatype) {
2248    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2249    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2250}
2251
2252TEST_F(DcpBufferAckValidatorTest, InvalidBody) {
2253    request.message.header.request.bodylen = htonl(12);
2254    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2255}
2256
2257class DcpControlValidatorTest : public ValidatorTest {
2258    void SetUp() override {
2259        ValidatorTest::SetUp();
2260        request.message.header.request.keylen = htons(4);
2261        request.message.header.request.bodylen = htonl(8);
2262    }
2263
2264protected:
2265    protocol_binary_response_status validate() {
2266        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_DCP_CONTROL,
2267                                       static_cast<void*>(&request));
2268    }
2269};
2270
2271TEST_F(DcpControlValidatorTest, CorrectMessage) {
2272    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, validate());
2273}
2274
2275TEST_F(DcpControlValidatorTest, InvalidMagic) {
2276    request.message.header.request.magic = 0;
2277    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2278}
2279
2280TEST_F(DcpControlValidatorTest, InvalidExtlen) {
2281    request.message.header.request.extlen = 5;
2282    request.message.header.request.bodylen = htonl(13);
2283    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2284}
2285
2286TEST_F(DcpControlValidatorTest, InvalidKeylen) {
2287    request.message.header.request.keylen = 0;
2288    request.message.header.request.bodylen = htonl(4);
2289    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2290}
2291
2292TEST_F(DcpControlValidatorTest, InvalidDatatype) {
2293    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2294    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2295}
2296
2297TEST_F(DcpControlValidatorTest, InvalidBody) {
2298    request.message.header.request.bodylen = htonl(4);
2299    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2300}
2301
2302// Test observe seqno
2303class ObserveSeqnoValidatorTest : public ValidatorTest {
2304    void SetUp() override {
2305        ValidatorTest::SetUp();
2306        request.message.header.request.bodylen = ntohl(8);
2307    }
2308
2309protected:
2310    protocol_binary_response_status validate() {
2311        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_OBSERVE_SEQNO,
2312                                       static_cast<void*>(&request));
2313    }
2314};
2315
2316TEST_F(ObserveSeqnoValidatorTest, CorrectMessage) {
2317    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
2318}
2319
2320TEST_F(ObserveSeqnoValidatorTest, InvalidMagic) {
2321    request.message.header.request.magic = 0;
2322    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2323}
2324
2325TEST_F(ObserveSeqnoValidatorTest, InvalidExtlen) {
2326    request.message.header.request.extlen = 8;
2327    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2328}
2329
2330TEST_F(ObserveSeqnoValidatorTest, InvalidKey) {
2331    request.message.header.request.keylen = 10;
2332    request.message.header.request.bodylen = htonl(18);
2333    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2334}
2335
2336TEST_F(ObserveSeqnoValidatorTest, InvalidDatatype) {
2337    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2338    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2339}
2340
2341TEST_F(ObserveSeqnoValidatorTest, InvalidBody) {
2342    request.message.header.request.bodylen = htonl(12);
2343    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2344}
2345
2346// Test set drift counter state
2347class SetDriftCounterStateValidatorTest : public ValidatorTest {
2348    void SetUp() override {
2349        ValidatorTest::SetUp();
2350        request.message.header.request.extlen = 9;
2351        request.message.header.request.bodylen = ntohl(9);
2352    }
2353
2354protected:
2355    protocol_binary_response_status validate() {
2356        return ValidatorTest::validate(
2357            PROTOCOL_BINARY_CMD_SET_DRIFT_COUNTER_STATE,
2358            static_cast<void*>(&request));
2359    }
2360};
2361
2362TEST_F(SetDriftCounterStateValidatorTest, CorrectMessage) {
2363    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
2364}
2365
2366TEST_F(SetDriftCounterStateValidatorTest, InvalidMagic) {
2367    request.message.header.request.magic = 0;
2368    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2369}
2370
2371TEST_F(SetDriftCounterStateValidatorTest, InvalidExtlen) {
2372    request.message.header.request.extlen = 2;
2373    request.message.header.request.bodylen = htonl(2);
2374    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2375}
2376
2377TEST_F(SetDriftCounterStateValidatorTest, InvalidKey) {
2378    request.message.header.request.keylen = 10;
2379    request.message.header.request.bodylen = htonl(19);
2380    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2381}
2382
2383TEST_F(SetDriftCounterStateValidatorTest, InvalidDatatype) {
2384    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2385    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2386}
2387
2388TEST_F(SetDriftCounterStateValidatorTest, InvalidBody) {
2389    request.message.header.request.bodylen = htonl(4);
2390    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2391}
2392
2393// Test get adjusted time
2394class GetAdjustedTimeValidatorTest : public ValidatorTest {
2395protected:
2396    protocol_binary_response_status validate() {
2397        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_GET_ADJUSTED_TIME,
2398                                       static_cast<void*>(&request));
2399    }
2400};
2401
2402TEST_F(GetAdjustedTimeValidatorTest, CorrectMessage) {
2403    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
2404}
2405
2406TEST_F(GetAdjustedTimeValidatorTest, InvalidMagic) {
2407    request.message.header.request.magic = 0;
2408    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2409}
2410
2411TEST_F(GetAdjustedTimeValidatorTest, InvalidExtlen) {
2412    request.message.header.request.extlen = 2;
2413    request.message.header.request.bodylen = htonl(2);
2414    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2415}
2416
2417TEST_F(GetAdjustedTimeValidatorTest, InvalidKey) {
2418    request.message.header.request.keylen = 10;
2419    request.message.header.request.bodylen = htonl(10);
2420    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2421}
2422
2423TEST_F(GetAdjustedTimeValidatorTest, InvalidDatatype) {
2424    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2425    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2426}
2427
2428TEST_F(GetAdjustedTimeValidatorTest, InvalidCas) {
2429    request.message.header.request.cas = 1;
2430    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2431}
2432
2433TEST_F(GetAdjustedTimeValidatorTest, InvalidBody) {
2434    request.message.header.request.bodylen = htonl(4);
2435    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2436}
2437
2438enum class RefreshOpcodes : uint8_t {
2439    Isasl = uint8_t(PROTOCOL_BINARY_CMD_ISASL_REFRESH),
2440    Ssl = uint8_t(PROTOCOL_BINARY_CMD_SSL_CERTS_REFRESH),
2441    Rbac = uint8_t(PROTOCOL_BINARY_CMD_RBAC_REFRESH)
2442};
2443
2444std::string to_string(const RefreshOpcodes& opcode) {
2445#ifdef JETBRAINS_CLION_IDE
2446    // CLion don't properly parse the output when the
2447    // output gets written as the string instead of the
2448    // number. This makes it harder to debug the tests
2449    // so let's just disable it while we're waiting
2450    // for them to supply a fix.
2451    // See https://youtrack.jetbrains.com/issue/CPP-6039
2452    return std::to_string(static_cast<int>(opcode));
2453#else
2454    switch (opcode) {
2455    case RefreshOpcodes::Isasl:
2456        return "ISASL";
2457    case RefreshOpcodes::Ssl:
2458        return "SSL";
2459    case RefreshOpcodes::Rbac:
2460        return "RBAC";
2461    }
2462    throw std::invalid_argument("to_string(const RefreshOpcodes&): unknown opcode");
2463#endif
2464}
2465
2466std::ostream& operator<<(std::ostream& os, const RefreshOpcodes& o) {
2467    os << to_string(o);
2468    return os;
2469}
2470
2471class RefreshValidatorTest : public ValidatorTest,
2472                             public ::testing::WithParamInterface<RefreshOpcodes> {
2473protected:
2474    protocol_binary_response_status validate() {
2475        auto opcode = (protocol_binary_command)GetParam();
2476        return ValidatorTest::validate(opcode, static_cast<void*>(&request));
2477    }
2478};
2479
2480INSTANTIATE_TEST_CASE_P(RefreshOpcodes,
2481                        RefreshValidatorTest,
2482                        ::testing::Values(RefreshOpcodes::Isasl,
2483                                          RefreshOpcodes::Ssl,
2484                                          RefreshOpcodes::Rbac),
2485                        ::testing::PrintToStringParamName());
2486
2487
2488TEST_P(RefreshValidatorTest, CorrectMessage) {
2489    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
2490}
2491
2492TEST_P(RefreshValidatorTest, InvalidMagic) {
2493    request.message.header.request.magic = 0;
2494    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2495}
2496
2497TEST_P(RefreshValidatorTest, InvalidExtlen) {
2498    request.message.header.request.extlen = 2;
2499    request.message.header.request.bodylen = htonl(2);
2500    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2501}
2502
2503TEST_P(RefreshValidatorTest, InvalidKey) {
2504    request.message.header.request.keylen = 10;
2505    request.message.header.request.bodylen = htonl(10);
2506    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2507}
2508
2509TEST_P(RefreshValidatorTest, InvalidDatatype) {
2510    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2511    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2512}
2513
2514TEST_P(RefreshValidatorTest, InvalidCas) {
2515    request.message.header.request.cas = 1;
2516    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2517}
2518
2519TEST_P(RefreshValidatorTest, InvalidBody) {
2520    request.message.header.request.bodylen = htonl(4);
2521    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2522}
2523
2524// Test CmdTimer
2525class CmdTimerValidatorTest : public ValidatorTest {
2526    void SetUp() override {
2527        ValidatorTest::SetUp();
2528        request.message.header.request.extlen = 1;
2529        request.message.header.request.bodylen = htonl(1);
2530    }
2531
2532protected:
2533    protocol_binary_response_status validate() {
2534        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_GET_CMD_TIMER,
2535                                       static_cast<void*>(&request));
2536    }
2537};
2538
2539TEST_F(CmdTimerValidatorTest, CorrectMessage) {
2540    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
2541}
2542
2543TEST_F(CmdTimerValidatorTest, InvalidMagic) {
2544    request.message.header.request.magic = 0;
2545    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2546}
2547
2548TEST_F(CmdTimerValidatorTest, InvalidExtlen) {
2549    request.message.header.request.extlen = 2;
2550    request.message.header.request.bodylen = htonl(2);
2551    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2552}
2553
2554TEST_F(CmdTimerValidatorTest, InvalidKey) {
2555    request.message.header.request.keylen = 10;
2556    request.message.header.request.bodylen = htonl(10);
2557    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2558}
2559
2560TEST_F(CmdTimerValidatorTest, InvalidDatatype) {
2561    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2562    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2563}
2564
2565TEST_F(CmdTimerValidatorTest, InvalidCas) {
2566    request.message.header.request.cas = 1;
2567    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2568}
2569
2570TEST_F(CmdTimerValidatorTest, InvalidBody) {
2571    request.message.header.request.bodylen = htonl(4);
2572    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2573}
2574
2575// Test GetCtrlToken
2576class GetCtrlTokenValidatorTest : public ValidatorTest {
2577protected:
2578    protocol_binary_response_status validate() {
2579        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_GET_CTRL_TOKEN,
2580                                       static_cast<void*>(&request));
2581    }
2582};
2583
2584TEST_F(GetCtrlTokenValidatorTest, CorrectMessage) {
2585    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
2586}
2587
2588TEST_F(GetCtrlTokenValidatorTest, InvalidMagic) {
2589    request.message.header.request.magic = 0;
2590    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2591}
2592
2593TEST_F(GetCtrlTokenValidatorTest, InvalidExtlen) {
2594    request.message.header.request.extlen = 2;
2595    request.message.header.request.bodylen = htonl(2);
2596    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2597}
2598
2599TEST_F(GetCtrlTokenValidatorTest, InvalidKey) {
2600    request.message.header.request.keylen = 10;
2601    request.message.header.request.bodylen = htonl(10);
2602    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2603}
2604
2605TEST_F(GetCtrlTokenValidatorTest, InvalidDatatype) {
2606    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2607    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2608}
2609
2610TEST_F(GetCtrlTokenValidatorTest, InvalidCas) {
2611    request.message.header.request.cas = 1;
2612    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2613}
2614
2615TEST_F(GetCtrlTokenValidatorTest, InvalidBody) {
2616    request.message.header.request.bodylen = htonl(4);
2617    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2618}
2619
2620// Test SetCtrlToken
2621class SetCtrlTokenValidatorTest : public ValidatorTest {
2622    void SetUp() override {
2623        ValidatorTest::SetUp();
2624        memset(&request, 0, sizeof(request));
2625        request.message.header.request.magic = PROTOCOL_BINARY_REQ;
2626        request.message.header.request.extlen = 8;
2627        request.message.header.request.bodylen = htonl(8);
2628        request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
2629        request.message.body.new_cas = 1;
2630    }
2631
2632protected:
2633    protocol_binary_response_status validate() {
2634        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_SET_CTRL_TOKEN,
2635                                       static_cast<void*>(&request));
2636    }
2637
2638    protocol_binary_request_set_ctrl_token &request =
2639        *reinterpret_cast<protocol_binary_request_set_ctrl_token*>(blob);
2640};
2641
2642TEST_F(SetCtrlTokenValidatorTest, CorrectMessage) {
2643    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
2644}
2645
2646TEST_F(SetCtrlTokenValidatorTest, Cas) {
2647    request.message.header.request.cas = 1;
2648    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
2649}
2650
2651TEST_F(SetCtrlTokenValidatorTest, InvalidMagic) {
2652    request.message.header.request.magic = 0;
2653    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2654}
2655
2656TEST_F(SetCtrlTokenValidatorTest, InvalidExtlen) {
2657    request.message.header.request.extlen = 2;
2658    request.message.header.request.bodylen = htonl(10);
2659    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2660}
2661
2662TEST_F(SetCtrlTokenValidatorTest, InvalidKey) {
2663    request.message.header.request.keylen = 10;
2664    request.message.header.request.bodylen = htonl(18);
2665    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2666}
2667
2668TEST_F(SetCtrlTokenValidatorTest, InvalidDatatype) {
2669    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2670    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2671}
2672
2673TEST_F(SetCtrlTokenValidatorTest, InvalidNewCas) {
2674    request.message.body.new_cas = 0;
2675    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2676}
2677
2678TEST_F(SetCtrlTokenValidatorTest, InvalidBody) {
2679    request.message.header.request.bodylen = htonl(12);
2680    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2681}
2682
2683// PROTOCOL_BINARY_CMD_GET_ALL_VB_SEQNOS
2684class GetAllVbSeqnoValidatorTest : public ValidatorTest {
2685    void SetUp() override {
2686        ValidatorTest::SetUp();
2687        memset(&request, 0, sizeof(request));
2688        request.message.header.request.magic = PROTOCOL_BINARY_REQ;
2689        request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
2690    }
2691
2692protected:
2693    protocol_binary_response_status validate() {
2694        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_GET_ALL_VB_SEQNOS,
2695                                       static_cast<void*>(&request));
2696    }
2697
2698    protocol_binary_request_get_all_vb_seqnos &request =
2699        *reinterpret_cast<protocol_binary_request_get_all_vb_seqnos*>(blob);
2700};
2701
2702TEST_F(GetAllVbSeqnoValidatorTest, CorrectMessageNoState) {
2703    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
2704}
2705
2706TEST_F(GetAllVbSeqnoValidatorTest, CorrectMessageWithState) {
2707    EXPECT_EQ(4, sizeof(vbucket_state_t));
2708    request.message.header.request.extlen = 4;
2709    request.message.header.request.bodylen = htonl(4);
2710    request.message.body.state =
2711        static_cast<vbucket_state_t>(htonl(vbucket_state_active));
2712    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
2713}
2714
2715TEST_F(GetAllVbSeqnoValidatorTest, InvalidMagic) {
2716    request.message.header.request.magic = 0;
2717    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2718}
2719
2720TEST_F(GetAllVbSeqnoValidatorTest, InvalidExtlen) {
2721    request.message.header.request.extlen = 2;
2722    request.message.header.request.bodylen = htonl(2);
2723    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2724}
2725
2726TEST_F(GetAllVbSeqnoValidatorTest, InvalidKey) {
2727    request.message.header.request.keylen = 10;
2728    request.message.header.request.bodylen = htonl(10);
2729    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2730}
2731
2732TEST_F(GetAllVbSeqnoValidatorTest, InvalidDatatype) {
2733    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2734    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2735}
2736
2737TEST_F(GetAllVbSeqnoValidatorTest, InvalidCas) {
2738    request.message.header.request.cas = 1;
2739    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2740}
2741
2742TEST_F(GetAllVbSeqnoValidatorTest, InvalidBody) {
2743    request.message.header.request.bodylen = htonl(4);
2744    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2745}
2746
2747TEST_F(GetAllVbSeqnoValidatorTest, InvalidBodylen) {
2748    request.message.header.request.bodylen = htonl(1);
2749    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2750}
2751
2752TEST_F(GetAllVbSeqnoValidatorTest, InvalidVbucketState) {
2753    request.message.header.request.extlen = 4;
2754    request.message.header.request.bodylen = htonl(4);
2755
2756    for (int ii = 0; ii < 100; ++ii) {
2757        request.message.body.state = static_cast<vbucket_state_t>(htonl(ii));
2758        if (is_valid_vbucket_state_t(static_cast<vbucket_state_t>(ii))) {
2759            EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
2760        } else {
2761            EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2762        }
2763    }
2764}
2765
2766// PROTOCOL_BINARY_CMD_GET_LOCKED
2767class GetLockedValidatorTest : public ValidatorTest {
2768    void SetUp() override {
2769        ValidatorTest::SetUp();
2770        request.message.header.request.keylen = htons(10);
2771        request.message.header.request.bodylen = htonl(10);
2772    }
2773
2774protected:
2775    protocol_binary_response_status validate() {
2776        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_GET_LOCKED,
2777                                       static_cast<void*>(&request));
2778    }
2779};
2780
2781TEST_F(GetLockedValidatorTest, CorrectMessageDefaultTimeout) {
2782    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
2783}
2784
2785TEST_F(GetLockedValidatorTest, CorrectMessageExplicitTimeout) {
2786    request.message.header.request.extlen = 4;
2787    request.message.header.request.bodylen = htonl(14);
2788    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
2789}
2790
2791TEST_F(GetLockedValidatorTest, InvalidMagic) {
2792    request.message.header.request.magic = 0;
2793    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2794}
2795
2796TEST_F(GetLockedValidatorTest, InvalidExtlen) {
2797    request.message.header.request.extlen = 2;
2798    request.message.header.request.bodylen = htonl(12);
2799    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2800}
2801
2802TEST_F(GetLockedValidatorTest, InvalidKey) {
2803    request.message.header.request.keylen = 10;
2804    request.message.header.request.bodylen = htonl(11);
2805    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2806}
2807
2808TEST_F(GetLockedValidatorTest, InvalidDatatype) {
2809    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2810    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2811}
2812
2813TEST_F(GetLockedValidatorTest, InvalidCas) {
2814    request.message.header.request.cas = 1;
2815    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2816}
2817
2818TEST_F(GetLockedValidatorTest, InvalidBody) {
2819    request.message.header.request.bodylen = htonl(4);
2820    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2821}
2822
2823TEST_F(GetLockedValidatorTest, InvalidBodylen) {
2824    request.message.header.request.bodylen = htonl(1);
2825    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2826}
2827
2828// PROTOCOL_BINARY_CMD_UNLOCK
2829class UnlockValidatorTest : public ValidatorTest {
2830    void SetUp() override {
2831        ValidatorTest::SetUp();
2832        request.message.header.request.keylen = htons(10);
2833        request.message.header.request.bodylen = htonl(10);
2834        request.message.header.request.cas = 0xdeadbeef;
2835    }
2836
2837protected:
2838    protocol_binary_response_status validate() {
2839        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_UNLOCK_KEY,
2840                                       static_cast<void*>(&request));
2841    }
2842};
2843
2844TEST_F(UnlockValidatorTest, CorrectMessage) {
2845    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
2846}
2847
2848TEST_F(UnlockValidatorTest, InvalidMagic) {
2849    request.message.header.request.magic = 0;
2850    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2851}
2852
2853TEST_F(UnlockValidatorTest, InvalidExtlen) {
2854    request.message.header.request.extlen = 2;
2855    request.message.header.request.bodylen = htonl(12);
2856    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2857}
2858
2859TEST_F(UnlockValidatorTest, InvalidKey) {
2860    request.message.header.request.keylen = 10;
2861    request.message.header.request.bodylen = htonl(11);
2862    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2863}
2864
2865TEST_F(UnlockValidatorTest, InvalidDatatype) {
2866    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2867    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2868}
2869
2870TEST_F(UnlockValidatorTest, InvalidCas) {
2871    request.message.header.request.cas = 0;
2872    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2873}
2874
2875TEST_F(UnlockValidatorTest, InvalidBody) {
2876    request.message.header.request.bodylen = htonl(4);
2877    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2878}
2879
2880TEST_F(UnlockValidatorTest, InvalidBodylen) {
2881    request.message.header.request.bodylen = htonl(1);
2882    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2883}
2884
2885// Test config_reload
2886class ConfigReloadValidatorTest : public ValidatorTest {
2887protected:
2888    protocol_binary_response_status validate() {
2889        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_CONFIG_RELOAD,
2890                                       static_cast<void*>(&request));
2891    }
2892};
2893
2894TEST_F(ConfigReloadValidatorTest, CorrectMessage) {
2895    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
2896}
2897
2898TEST_F(ConfigReloadValidatorTest, InvalidMagic) {
2899    request.message.header.request.magic = 0;
2900    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2901}
2902
2903TEST_F(ConfigReloadValidatorTest, InvalidExtlen) {
2904    request.message.header.request.extlen = 2;
2905    request.message.header.request.bodylen = htonl(2);
2906    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2907}
2908
2909TEST_F(ConfigReloadValidatorTest, InvalidKey) {
2910    request.message.header.request.keylen = 10;
2911    request.message.header.request.bodylen = htonl(10);
2912    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2913}
2914
2915TEST_F(ConfigReloadValidatorTest, InvalidDatatype) {
2916    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2917    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2918}
2919
2920TEST_F(ConfigReloadValidatorTest, InvalidCas) {
2921    request.message.header.request.cas = 1;
2922    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2923}
2924
2925TEST_F(ConfigReloadValidatorTest, InvalidBody) {
2926    request.message.header.request.bodylen = htonl(4);
2927    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2928}
2929
2930// PROTOCOL_BINARY_CMD_EVICT_KEY
2931class EvictKeyValidatorTest : public ValidatorTest {
2932    virtual void SetUp() override {
2933        ValidatorTest::SetUp();
2934        request.message.header.request.keylen = htons(10);
2935        request.message.header.request.bodylen = htonl(10);
2936        request.message.header.request.cas = 0;
2937    }
2938
2939protected:
2940    protocol_binary_response_status validate() {
2941        return ValidatorTest::validate(PROTOCOL_BINARY_CMD_EVICT_KEY,
2942                                       static_cast<void*>(&request));
2943    }
2944};
2945
2946TEST_F(EvictKeyValidatorTest, CorrectMessage) {
2947    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_SUCCESS, validate());
2948}
2949
2950TEST_F(EvictKeyValidatorTest, InvalidMagic) {
2951    request.message.header.request.magic = 0;
2952    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2953}
2954
2955TEST_F(EvictKeyValidatorTest, InvalidExtlen) {
2956    request.message.header.request.extlen = 2;
2957    request.message.header.request.bodylen = htonl(12);
2958    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2959}
2960
2961TEST_F(EvictKeyValidatorTest, InvalidKey) {
2962    request.message.header.request.keylen = 10;
2963    request.message.header.request.bodylen = htonl(11);
2964    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2965}
2966
2967TEST_F(EvictKeyValidatorTest, InvalidDatatype) {
2968    request.message.header.request.datatype = PROTOCOL_BINARY_DATATYPE_JSON;
2969    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2970}
2971
2972TEST_F(EvictKeyValidatorTest, InvalidCas) {
2973    request.message.header.request.cas = 0xff;
2974    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2975}
2976
2977TEST_F(EvictKeyValidatorTest, InvalidBody) {
2978    request.message.header.request.bodylen = htonl(4);
2979    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2980}
2981
2982TEST_F(EvictKeyValidatorTest, InvalidBodylen) {
2983    request.message.header.request.bodylen = htonl(1);
2984    EXPECT_EQ(PROTOCOL_BINARY_RESPONSE_EINVAL, validate());
2985}
2986
2987} // namespace test
2988} // namespace mcbp
2989