1
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
9
#include "basic_engine_testsuite.h"
11
struct test_harness test_harness;
14
* Make sure that get_info returns something and that repeated calls to it
15
* return the same something.
17
static enum test_result get_info_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
18
const engine_info *info = h1->get_info(h);
20
assert(info == h1->get_info(h));
25
* Make sure that the structure returned by get_info has a non-null description.
27
static enum test_result get_info_description_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
28
const engine_info *info = h1->get_info(h);
29
assert(info->description != NULL);
34
* Make sure that the structure returned by get_info has a valid number of
35
* features and that the size of the feautes array equals that value
37
static enum test_result get_info_features_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
38
const engine_info *info = h1->get_info(h);
39
uint32_t nfeats = info->num_features;
41
const feature_info *fi = info->features;
42
while (nfeats-- > 0) {
50
* Make sure we can successfully allocate an item, allocate op returns success
51
* and that item struct is populated
53
static enum test_result allocate_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
54
item *test_item = NULL;
56
assert(h1->allocate(h, NULL, &test_item, key, strlen(key), 1,1,1) == ENGINE_SUCCESS);
57
assert(test_item != NULL);
58
h1->release(h,NULL,test_item);
65
static enum test_result set_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
68
assert(h1->allocate(h, NULL, &it, key,
69
strlen(key), 1, 1, 0) == ENGINE_SUCCESS);
74
for (int ii = 0; ii < 10; ++ii) {
76
assert(h1->store(h, NULL, it, &cas, OPERATION_SET,0) == ENGINE_SUCCESS);
77
assert(cas != prev_cas);
79
h1->release(h, NULL, it);
86
static enum test_result add_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
89
assert(h1->allocate(h, NULL, &it, key,
90
strlen(key), 1, 1, 0) == ENGINE_SUCCESS);
93
for (int ii = 0; ii < 10; ++ii) {
94
ENGINE_ERROR_CODE ret = h1->store(h, NULL, it, &cas, OPERATION_ADD, 0);
96
assert(ret == ENGINE_SUCCESS);
99
assert(ret == ENGINE_NOT_STORED);
102
h1->release(h, NULL, it);
107
* Verify replace behavior
109
static enum test_result replace_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
112
assert(set_test(h, h1) == SUCCESS);
114
assert(h1->allocate(h, NULL, &it, key,
115
strlen(key), sizeof(int), 1, 0) == ENGINE_SUCCESS);
116
item_info item_info = { .nvalue = 1 };
117
assert(h1->get_item_info(h, NULL, it, &item_info) == true);
122
for (int ii = 0; ii < 10; ++ii) {
124
*(int*)(item_info.value[0].iov_base) = ii;
125
assert(h1->store(h, NULL, it, &cas, OPERATION_REPLACE,0) == ENGINE_SUCCESS);
126
assert(cas != prev_cas);
128
h1->release(h, NULL, it);
130
assert(h1->get(h, NULL, &it, key, strlen(key), 0) == ENGINE_SUCCESS);
131
assert(h1->get_item_info(h, NULL, it, &item_info) == true);
132
assert(item_info.value[0].iov_len == sizeof(int));
133
assert(*(int*)(item_info.value[0].iov_base) == 9);
134
h1->release(h, NULL, it);
140
* Verify append behavior
142
static enum test_result append_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
147
assert(h1->allocate(h, NULL, &it, key,
148
strlen(key), 5, 1, 0) == ENGINE_SUCCESS);
149
item_info item_info = { .nvalue = 1 };
150
assert(h1->get_item_info(h, NULL, it, &item_info) == true);
151
memcpy(item_info.value[0].iov_base, "HELLO", 5);
152
assert(h1->store(h, NULL, it, &cas, OPERATION_SET, 0) == ENGINE_SUCCESS);
153
h1->release(h, NULL, it);
154
assert(h1->allocate(h, NULL, &it, key,
155
strlen(key), 6, 1, 0) == ENGINE_SUCCESS);
156
item_info.nvalue = 1;
157
assert(h1->get_item_info(h, NULL, it, &item_info) == true);
158
memcpy(item_info.value[0].iov_base, " WORLD", 6);
159
assert(h1->store(h, NULL, it, &cas, OPERATION_APPEND, 0) == ENGINE_SUCCESS);
160
h1->release(h, NULL, it);
162
assert(h1->get(h, NULL, &it, key, strlen(key), 0) == ENGINE_SUCCESS);
163
assert(h1->get_item_info(h, NULL, it, &item_info) == true);
164
assert(item_info.value[0].iov_len == 11);
165
assert(memcmp(item_info.value[0].iov_base, "HELLO WORLD", 11) == 0);
166
h1->release(h, NULL, it);
172
* Verify prepend behavior
174
static enum test_result prepend_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
179
assert(h1->allocate(h, NULL, &it, key,
180
strlen(key), 5, 1, 0) == ENGINE_SUCCESS);
181
item_info item_info = { .nvalue = 1 };
182
assert(h1->get_item_info(h, NULL, it, &item_info) == true);
183
memcpy(item_info.value[0].iov_base, "HELLO", 5);
184
assert(h1->store(h, NULL, it, &cas, OPERATION_SET, 0) == ENGINE_SUCCESS);
185
h1->release(h, NULL, it);
186
assert(h1->allocate(h, NULL, &it, key,
187
strlen(key), 6, 1, 0) == ENGINE_SUCCESS);
188
item_info.nvalue = 1;
189
assert(h1->get_item_info(h, NULL, it, &item_info) == true);
190
memcpy(item_info.value[0].iov_base, " WORLD", 6);
191
assert(h1->store(h, NULL, it, &cas, OPERATION_PREPEND, 0) == ENGINE_SUCCESS);
192
h1->release(h, NULL, it);
194
assert(h1->get(h, NULL, &it, key, strlen(key), 0) == ENGINE_SUCCESS);
195
assert(h1->get_item_info(h, NULL, it, &item_info) == true);
196
assert(item_info.value[0].iov_len == 11);
197
assert(memcmp(item_info.value[0].iov_base, " WORLDHELLO", 11) == 0);
198
h1->release(h, NULL, it);
204
* Make sure when we can successfully store an item after it has been allocated
205
* and that the cas for the stored item has been generated.
207
static enum test_result store_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
208
item *test_item = NULL;
211
assert(h1->allocate(h, NULL, &test_item, key, strlen(key), 1,1,1) == ENGINE_SUCCESS);
212
assert(h1->store(h, NULL, test_item, &cas, OPERATION_SET,0) == ENGINE_SUCCESS);
214
h1->release(h,NULL,test_item);
219
* Make sure when we can successfully retrieve an item that has been stored in
222
static enum test_result get_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
223
item *test_item = NULL;
224
item *test_item_get = NULL;
225
void *key = "get_test_key";
227
assert(h1->allocate(h, NULL, &test_item, key, strlen(key), 1,0, 0) == ENGINE_SUCCESS);
228
assert(h1->store(h, NULL, test_item, &cas, OPERATION_SET,0) == ENGINE_SUCCESS);
229
assert(h1->get(h,NULL,&test_item_get,key,strlen(key),0) == ENGINE_SUCCESS);
230
h1->release(h,NULL,test_item);
231
h1->release(h,NULL,test_item_get);
235
static enum test_result expiry_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
236
item *test_item = NULL;
237
item *test_item_get = NULL;
238
void *key = "get_test_key";
240
assert(h1->allocate(h, NULL, &test_item, key, strlen(key), 1, 0, 10) == ENGINE_SUCCESS);
241
assert(h1->store(h, NULL, test_item, &cas, OPERATION_SET, 0) == ENGINE_SUCCESS);
242
test_harness.time_travel(11);
243
assert(h1->get(h,NULL,&test_item_get,key,strlen(key),0) == ENGINE_KEY_ENOENT);
244
h1->release(h,NULL,test_item);
249
* Make sure that we can release an item. For the most part all this test does
250
* is ensure that thinds dont go splat when we call release. It does nothing to
251
* ensure that release did much of anything.
253
static enum test_result release_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
254
item *test_item = NULL;
255
void *key = "release_test_key";
257
assert(h1->allocate(h, NULL, &test_item, key, strlen(key), 1, 0, 0) == ENGINE_SUCCESS);
258
assert(h1->store(h, NULL, test_item, &cas, OPERATION_SET,0) == ENGINE_SUCCESS);
259
h1->release(h, NULL, test_item);
264
* Make sure that we can remove an item and that after the item has been
265
* removed it can not be retrieved.
267
static enum test_result remove_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
268
item *test_item = NULL;
269
void *key = "remove_test_key";
271
assert(h1->allocate(h, NULL, &test_item, key, strlen(key), 1,0, 0) == ENGINE_SUCCESS);
272
assert(h1->store(h, NULL, test_item, &cas, OPERATION_SET,0) == ENGINE_SUCCESS);
273
assert(h1->remove(h, NULL, key, strlen(key), cas, 0) == ENGINE_SUCCESS);
274
item *check_item = test_item;
275
assert(h1->get(h, NULL, &check_item, key, strlen(key), 0) == ENGINE_KEY_ENOENT);
276
assert(check_item == NULL);
277
h1->release(h, NULL, test_item);
282
* Make sure we can arithmetic operations to set the initial value of a key and
283
* to then later increment that value
285
static enum test_result incr_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
286
item *test_item = NULL;
287
void *key = "incr_test_key";
290
assert(h1->allocate(h, NULL, &test_item, key, strlen(key), 1, 0, 0) == ENGINE_SUCCESS);
291
assert(h1->arithmetic(h, NULL, key, strlen(key), true, true, 0, 1,
292
0, &cas, &res, 0 ) == ENGINE_SUCCESS);
294
assert(h1->arithmetic(h, NULL, key, strlen(key), true, false, 1, 0,
295
0, &cas, &res, 0 ) == ENGINE_SUCCESS);
297
h1->release(h, NULL, test_item);
301
static void *incr_test_main(void *arg) {
302
ENGINE_HANDLE *h = arg;
303
ENGINE_HANDLE_V1 *h1 = arg;
304
void *key = "incr_test_key";
308
for (int ii = 0; ii < 1000; ++ii) {
309
assert(h1->arithmetic(h, NULL, key, strlen(key), false, false, 1, 0,
310
0, &cas, &res, 0 ) == ENGINE_SUCCESS);
319
* Make sure we can arithmetic operations to set the initial value of a key and
320
* to then later increment that value
322
static enum test_result mt_incr_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
324
const int max_threads = 1;
326
const int max_threads = 30;
328
pthread_t tid[max_threads];
330
if (max_threads < 2) {
334
item *test_item = NULL;
335
void *key = "incr_test_key";
338
assert(h1->allocate(h, NULL, &test_item, key,
339
strlen(key), 1, 0, 0) == ENGINE_SUCCESS);
340
assert(h1->arithmetic(h, NULL, key, strlen(key), true, true, 0, 1,
341
0, &cas, &res, 0 ) == ENGINE_SUCCESS);
342
h1->release(h, NULL, test_item);
344
for (int ii = 0; ii < max_threads; ++ii) {
345
assert(pthread_create(&tid[ii], NULL, incr_test_main, h) == 0);
348
for (int ii = 0; ii < max_threads; ++ii) {
350
assert(pthread_join(tid[ii], &ret) == 0);
358
* Make sure we can arithmetic operations to set the initial value of a key and
359
* to then later decrement that value
361
static enum test_result decr_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
362
item *test_item = NULL;
363
void *key = "decr_test_key";
366
assert(h1->allocate(h, NULL, &test_item, key, strlen(key), 1,0, 0) == ENGINE_SUCCESS);
367
assert(h1->arithmetic(h, NULL, key, strlen(key), false, true, 0, 1,
368
0, &cas, &res, 0 ) == ENGINE_SUCCESS);
370
assert(h1->arithmetic(h, NULL, key, strlen(key), false, false, 1, 0,
371
0, &cas, &res, 0 ) == ENGINE_SUCCESS);
373
h1->release(h, NULL, test_item);
378
* Make sure we can successfully perform a flush operation and that any item
379
* stored before the flush can not be retrieved
381
static enum test_result flush_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
382
item *test_item = NULL;
383
void *key = "flush_test_key";
385
test_harness.time_travel(3);
386
assert(h1->allocate(h, NULL, &test_item, key, strlen(key), 1, 0, 0) == ENGINE_SUCCESS);
387
assert(h1->store(h, NULL, test_item, &cas, OPERATION_SET,0) == ENGINE_SUCCESS);
388
assert(h1->flush(h, NULL, 0) == ENGINE_SUCCESS);
389
item *check_item = test_item;
390
assert(h1->get(h, NULL, &check_item, key, strlen(key), 0) == ENGINE_KEY_ENOENT);
391
assert(check_item == NULL);
392
h1->release(h, NULL, test_item);
397
* Make sure we can successfully retrieve the item info struct for an item and
398
* that the contents of the item_info are as expected.
400
static enum test_result get_item_info_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
401
item *test_item = NULL;
402
char *key = "get_item_info_test_key";
404
const rel_time_t exp = 1;
405
item_info ii = { .nvalue = 1 };
406
assert(h1->allocate(h, NULL, &test_item, key, strlen(key), 1,0, exp) == ENGINE_SUCCESS);
407
assert(h1->store(h, NULL, test_item, &cas, OPERATION_SET,0) == ENGINE_SUCCESS);
408
/* Had this been actual code, there'd be a connection here */
409
assert(h1->get_item_info(h, NULL, test_item, &ii) == true);
410
assert(ii.cas == cas);
411
assert(ii.flags == 0);
412
assert(strcmp(key,ii.key) == 0);
413
assert(ii.nkey == strlen(key));
414
assert(ii.nbytes == 1);
415
assert(ii.exptime == exp);
416
h1->release(h, NULL, test_item);
420
static enum test_result item_set_cas_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
421
item *test_item = NULL;
422
char *key = "item_set_cas_test_key";
424
const rel_time_t exp = 1;
425
item_info ii = { .nvalue = 1 };
426
assert(h1->allocate(h, NULL, &test_item, key, strlen(key), 1,0, exp) == ENGINE_SUCCESS);
427
assert(h1->store(h, NULL, test_item, &cas, OPERATION_SET,0) == ENGINE_SUCCESS);
428
uint64_t newcas = cas + 1;
429
h1->item_set_cas(h, NULL, test_item, newcas);
430
assert(h1->get_item_info(h, NULL, test_item, &ii) == true);
431
assert(ii.cas == newcas);
432
h1->release(h, NULL, test_item);
437
static void eviction_stats_handler(const char *key, const uint16_t klen,
438
const char *val, const uint32_t vlen,
439
const void *cookie) {
440
if (memcmp(key, "evictions", klen) == 0) {
441
char buffer[vlen + 1];
442
memcpy(buffer, val, vlen);
444
evictions = atoi(buffer);
448
static enum test_result lru_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
449
item *test_item = NULL;
450
const char *hot_key = "hot_key";
452
assert(h1->allocate(h, NULL, &test_item,
453
hot_key, strlen(hot_key), 4096, 0, 0) == ENGINE_SUCCESS);
454
assert(h1->store(h, NULL, test_item,
455
&cas, OPERATION_SET,0) == ENGINE_SUCCESS);
456
h1->release(h, NULL, test_item);
459
for (ii = 0; ii < 250; ++ii) {
460
assert(h1->get(h, NULL, &test_item,
461
hot_key, strlen(hot_key), 0) == ENGINE_SUCCESS);
462
h1->release(h, NULL, test_item);
464
size_t keylen = snprintf(key, sizeof(key), "lru_test_key_%08d", ii);
465
assert(h1->allocate(h, NULL, &test_item,
466
key, keylen, 4096, 0, 0) == ENGINE_SUCCESS);
467
assert(h1->store(h, NULL, test_item,
468
&cas, OPERATION_SET,0) == ENGINE_SUCCESS);
469
h1->release(h, NULL, test_item);
470
assert(h1->get_stats(h, NULL, NULL, 0,
471
eviction_stats_handler) == ENGINE_SUCCESS);
472
if (evictions == 2) {
478
for (int jj = 0; jj <= ii; ++jj) {
480
size_t keylen = snprintf(key, sizeof(key), "lru_test_key_%08d", jj);
481
if (jj == 0 || jj == 1) {
482
assert(h1->get(h, NULL, &test_item,
483
key, keylen, 0) == ENGINE_KEY_ENOENT);
485
assert(h1->get(h, NULL, &test_item,
486
key, keylen, 0) == ENGINE_SUCCESS);
487
assert(test_item != NULL);
488
h1->release(h, NULL, test_item);
494
static enum test_result get_stats_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
498
static enum test_result reset_stats_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
502
static enum test_result get_stats_struct_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
506
static enum test_result aggregate_stats_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
510
static protocol_binary_response_header *last_response;
512
static void release_last_response(void) {
514
last_response = NULL;
517
static bool response_handler(const void *key, uint16_t keylen,
518
const void *ext, uint8_t extlen,
519
const void *body, uint32_t bodylen,
520
uint8_t datatype, uint16_t status,
521
uint64_t cas, const void *cookie)
523
assert(last_response == NULL);
524
last_response = malloc(sizeof(*last_response) + keylen + extlen + bodylen);
525
if (last_response == NULL) {
528
protocol_binary_response_header *r = last_response;
529
r->response.magic = PROTOCOL_BINARY_RES;
530
r->response.opcode = 0xff; // we don't know this!
531
r->response.keylen = htons(keylen);
532
r->response.extlen = extlen;
533
r->response.datatype = PROTOCOL_BINARY_RAW_BYTES;
534
r->response.status = htons(status);
535
r->response.bodylen = htonl(keylen + extlen + bodylen);
536
r->response.opaque = 0xffffff; // we don't know this
537
r->response.cas = cas;
538
char *ptr = (void*)(r + 1);
539
memcpy(ptr, ext, extlen);
541
memcpy(ptr, key, keylen);
543
memcpy(ptr, body, bodylen);
548
static enum test_result touch_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
550
protocol_binary_request_touch touch;
554
void *key = "get_test_key";
555
size_t keylen = strlen(key);
560
.magic = PROTOCOL_BINARY_REQ,
561
.opcode = PROTOCOL_BINARY_CMD_TOUCH,
562
.keylen = htons((uint16_t)keylen),
564
.datatype = PROTOCOL_BINARY_RAW_BYTES,
566
.bodylen = htonl(keylen + 4),
567
.opaque = 0xdeadbeef,
571
.expiration = htonl(10)
577
memcpy(r.buffer + sizeof(r.touch.bytes), key, keylen);
578
ENGINE_ERROR_CODE ret;
579
ret = h1->unknown_command(h, NULL, &r.touch.message.header, response_handler);
580
assert(ret == ENGINE_SUCCESS);
581
assert(last_response != NULL);
582
assert(ntohs(last_response->response.status) == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT);
583
assert(last_response->response.keylen == 0);
584
assert(last_response->response.extlen == 0);
585
assert(last_response->response.bodylen == 0);
586
release_last_response();
588
// store and get a key
589
assert(get_test(h, h1) == SUCCESS);
591
// Set expiry time to 10 secs..
592
ret = h1->unknown_command(h, NULL, &r.touch.message.header, response_handler);
593
assert(ret == ENGINE_SUCCESS);
594
assert(last_response != NULL);
595
assert(ntohs(last_response->response.status) == PROTOCOL_BINARY_RESPONSE_SUCCESS);
596
assert(last_response->response.keylen == 0);
597
assert(last_response->response.extlen == 0);
598
assert(last_response->response.bodylen == 0);
599
release_last_response();
601
// time-travel 11 secs..
602
test_harness.time_travel(11);
604
// The item should have expired now...
606
assert(h1->get(h, NULL, &item, key, keylen, 0) == ENGINE_KEY_ENOENT);
608
// Verify that it doesn't accept bogus packets. extlen is mandatory
609
r.touch.message.header.request.extlen = 0;
610
r.touch.message.header.request.bodylen = htonl(keylen);
611
ret = h1->unknown_command(h, NULL, &r.touch.message.header, response_handler);
612
assert(ret == ENGINE_SUCCESS);
613
assert(last_response != NULL);
614
assert(ntohs(last_response->response.status) == PROTOCOL_BINARY_RESPONSE_EINVAL);
615
release_last_response();
618
r.touch.message.header.request.extlen = 4;
619
r.touch.message.header.request.keylen = 0;
620
r.touch.message.header.request.bodylen = htonl(4);
621
ret = h1->unknown_command(h, NULL, &r.touch.message.header, response_handler);
622
assert(ret == ENGINE_SUCCESS);
623
assert(last_response != NULL);
624
assert(ntohs(last_response->response.status) == PROTOCOL_BINARY_RESPONSE_EINVAL);
625
release_last_response();
630
static enum test_result gat_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
632
protocol_binary_request_gat gat;
636
void *key = "get_test_key";
637
size_t keylen = strlen(key);
642
.magic = PROTOCOL_BINARY_REQ,
643
.opcode = PROTOCOL_BINARY_CMD_GAT,
644
.keylen = htons((uint16_t)keylen),
646
.datatype = PROTOCOL_BINARY_RAW_BYTES,
648
.bodylen = htonl(keylen + 4),
649
.opaque = 0xdeadbeef,
653
.expiration = htonl(10)
659
memcpy(r.buffer + sizeof(r.gat.bytes), key, keylen);
660
ENGINE_ERROR_CODE ret;
661
ret = h1->unknown_command(h, NULL, &r.gat.message.header, response_handler);
662
assert(ret == ENGINE_SUCCESS);
663
assert(last_response != NULL);
664
assert(ntohs(last_response->response.status) == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT);
665
assert(last_response->response.keylen == 0);
666
assert(last_response->response.extlen == 0);
667
assert(last_response->response.bodylen == 0);
668
release_last_response();
670
// store and get a key
671
assert(get_test(h, h1) == SUCCESS);
673
// Set expiry time to 10 secs..
674
ret = h1->unknown_command(h, NULL, &r.gat.message.header, response_handler);
675
assert(ret == ENGINE_SUCCESS);
676
assert(last_response != NULL);
677
assert(ntohs(last_response->response.status) == PROTOCOL_BINARY_RESPONSE_SUCCESS);
678
assert(last_response->response.keylen == 0);
679
assert(last_response->response.extlen == 4);
680
assert(ntohl(last_response->response.bodylen) == 5); // get_test sets 1 byte datalen
681
release_last_response();
683
// time-travel 11 secs..
684
test_harness.time_travel(11);
686
// The item should have expired now...
688
assert(h1->get(h, NULL, &item, key, keylen, 0) == ENGINE_KEY_ENOENT);
690
// Verify that it doesn't accept bogus packets. extlen is mandatory
691
r.gat.message.header.request.extlen = 0;
692
r.gat.message.header.request.bodylen = htonl(keylen);
693
ret = h1->unknown_command(h, NULL, &r.gat.message.header, response_handler);
694
assert(ret == ENGINE_SUCCESS);
695
assert(last_response != NULL);
696
assert(ntohs(last_response->response.status) == PROTOCOL_BINARY_RESPONSE_EINVAL);
697
release_last_response();
700
r.gat.message.header.request.extlen = 4;
701
r.gat.message.header.request.keylen = 0;
702
r.gat.message.header.request.bodylen = htonl(4);
703
ret = h1->unknown_command(h, NULL, &r.gat.message.header, response_handler);
704
assert(ret == ENGINE_SUCCESS);
705
assert(last_response != NULL);
706
assert(ntohs(last_response->response.status) == PROTOCOL_BINARY_RESPONSE_EINVAL);
707
release_last_response();
712
static enum test_result gatq_test(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
714
protocol_binary_request_gat gat;
718
void *key = "get_test_key";
719
size_t keylen = strlen(key);
724
.magic = PROTOCOL_BINARY_REQ,
725
.opcode = PROTOCOL_BINARY_CMD_GATQ,
726
.keylen = htons((uint16_t)keylen),
728
.datatype = PROTOCOL_BINARY_RAW_BYTES,
730
.bodylen = htonl(keylen + 4),
731
.opaque = 0xdeadbeef,
735
.expiration = htonl(10)
741
memcpy(r.buffer + sizeof(r.gat.bytes), key, keylen);
742
ENGINE_ERROR_CODE ret;
743
ret = h1->unknown_command(h, NULL, &r.gat.message.header, response_handler);
744
assert(ret == ENGINE_SUCCESS);
746
// GATQ is quiet and should not produce any result
747
assert(last_response == NULL);
749
// store and get a key
750
assert(get_test(h, h1) == SUCCESS);
752
// Set expiry time to 10 secs..
753
ret = h1->unknown_command(h, NULL, &r.gat.message.header, response_handler);
754
assert(ret == ENGINE_SUCCESS);
755
assert(last_response != NULL);
756
assert(ntohs(last_response->response.status) == PROTOCOL_BINARY_RESPONSE_SUCCESS);
757
assert(last_response->response.keylen == 0);
758
assert(last_response->response.extlen == 4);
759
assert(ntohl(last_response->response.bodylen) == 5); // get_test sets 1 byte datalen
760
release_last_response();
762
// time-travel 11 secs..
763
test_harness.time_travel(11);
765
// The item should have expired now...
767
assert(h1->get(h, NULL, &item, key, keylen, 0) == ENGINE_KEY_ENOENT);
769
// Verify that it doesn't accept bogus packets. extlen is mandatory
770
r.gat.message.header.request.extlen = 0;
771
r.gat.message.header.request.bodylen = htonl(keylen);
772
ret = h1->unknown_command(h, NULL, &r.gat.message.header, response_handler);
773
assert(ret == ENGINE_SUCCESS);
774
assert(last_response != NULL);
775
assert(ntohs(last_response->response.status) == PROTOCOL_BINARY_RESPONSE_EINVAL);
776
release_last_response();
779
r.gat.message.header.request.extlen = 4;
780
r.gat.message.header.request.keylen = 0;
781
r.gat.message.header.request.bodylen = htonl(4);
782
ret = h1->unknown_command(h, NULL, &r.gat.message.header, response_handler);
783
assert(ret == ENGINE_SUCCESS);
784
assert(last_response != NULL);
785
assert(ntohs(last_response->response.status) == PROTOCOL_BINARY_RESPONSE_EINVAL);
786
release_last_response();
792
engine_test_t* get_tests(void) {
793
static engine_test_t tests[] = {
794
{"get info test", get_info_test, NULL, NULL, NULL},
795
{"get info description test", get_info_description_test, NULL, NULL, NULL},
796
{"get info features test", get_info_features_test, NULL, NULL, NULL},
797
{"allocate test", allocate_test, NULL, NULL, NULL},
798
{"set test", set_test, NULL, NULL, NULL},
799
{"add test", add_test, NULL, NULL, NULL},
800
{"replace test", replace_test, NULL, NULL, NULL},
801
{"append test", append_test, NULL, NULL, NULL},
802
{"prepend test", prepend_test, NULL, NULL, NULL},
803
{"store test", store_test, NULL, NULL, NULL},
804
{"get test", get_test, NULL, NULL, NULL},
805
{"expiry test", expiry_test, NULL, NULL, NULL},
806
{"remove test", remove_test, NULL, NULL, NULL},
807
{"release test", release_test, NULL, NULL, NULL},
808
{"incr test", incr_test, NULL, NULL, NULL},
809
{"mt incr test", mt_incr_test, NULL, NULL, NULL},
810
{"decr test", decr_test, NULL, NULL, NULL},
811
{"flush test", flush_test, NULL, NULL, NULL},
812
{"get item info test", get_item_info_test, NULL, NULL, NULL},
813
{"set cas test", item_set_cas_test, NULL, NULL, NULL},
814
{"LRU test", lru_test, NULL, NULL, "cache_size=48"},
815
{"get stats test", get_stats_test, NULL, NULL, NULL},
816
{"reset stats test", reset_stats_test, NULL, NULL, NULL},
817
{"get stats struct test", get_stats_struct_test, NULL, NULL, NULL},
818
{"aggregate stats test", aggregate_stats_test, NULL, NULL, NULL},
819
{"touch", touch_test, NULL, NULL, NULL},
820
{"Get And Touch", gat_test, NULL, NULL, NULL},
821
{"Get And Touch Quiet", gatq_test, NULL, NULL, NULL},
822
{NULL, NULL, NULL, NULL, NULL}
828
bool setup_suite(struct test_harness *th) {