1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 #include <stdlib.h>
3 #include <string.h>
4 #include <assert.h>
5
6 #include <memcached/engine.h>
7
8 #include "suite_stubs.h"
9
10 int expiry = 3600;
11 bool hasError = false;
12 struct test_harness testHarness;
13
14 static const char *key = "key";
15
test_setup(ENGINE_HANDLE * h,ENGINE_HANDLE_V1 * h1)16 bool test_setup(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
17 (void)h; (void)h1;
18 delay(2);
19 return true;
20 }
21
teardown(ENGINE_HANDLE * h,ENGINE_HANDLE_V1 * h1)22 bool teardown(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
23 (void)h; (void)h1;
24 return true;
25 }
26
delay(int amt)27 void delay(int amt) {
28 testHarness.time_travel(amt);
29 hasError = false;
30 }
31
storeItem(ENGINE_HANDLE * h,ENGINE_HANDLE_V1 * h1,ENGINE_STORE_OPERATION op)32 static void storeItem(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
33 ENGINE_STORE_OPERATION op) {
34 item *it = NULL;
35 uint64_t cas = 0;
36 char *value = "0";
37 const int flags = 0;
38 const void *cookie = NULL;
39
40 if (op == OPERATION_APPEND) {
41 value = "-suffix";
42 } else if (op == OPERATION_PREPEND) {
43 value = "prefix-";
44 }
45
46 size_t vlen = strlen(value);
47
48 ENGINE_ERROR_CODE rv = ENGINE_SUCCESS;
49
50 rv = h1->allocate(h, cookie, &it,
51 key, strlen(key),
52 vlen, flags, expiry);
53 assert(rv == ENGINE_SUCCESS);
54
55 item_info info;
56 info.nvalue = 1;
57 if (!h1->get_item_info(h, cookie, it, &info)) {
58 abort();
59 }
60
61 memcpy(info.value[0].iov_base, value, vlen);
62 h1->item_set_cas(h, cookie, it, 0);
63
64 rv = h1->store(h, cookie, it, &cas, op, 0);
65
66 hasError = rv != ENGINE_SUCCESS;
67 }
68
add(ENGINE_HANDLE * h,ENGINE_HANDLE_V1 * h1)69 void add(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
70 storeItem(h, h1, OPERATION_ADD);
71 }
72
append(ENGINE_HANDLE * h,ENGINE_HANDLE_V1 * h1)73 void append(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
74 storeItem(h, h1, OPERATION_APPEND);
75 }
76
decr(ENGINE_HANDLE * h,ENGINE_HANDLE_V1 * h1)77 void decr(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
78 uint64_t cas;
79 uint64_t result;
80 hasError = h1->arithmetic(h, NULL, key, strlen(key), false, false, 1, 0, expiry,
81 &cas, &result,
82 0) != ENGINE_SUCCESS;
83 }
84
decrWithDefault(ENGINE_HANDLE * h,ENGINE_HANDLE_V1 * h1)85 void decrWithDefault(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
86 uint64_t cas;
87 uint64_t result;
88 hasError = h1->arithmetic(h, NULL, key, strlen(key), false, true, 1, 0, expiry,
89 &cas, &result,
90 0) != ENGINE_SUCCESS;
91 }
92
prepend(ENGINE_HANDLE * h,ENGINE_HANDLE_V1 * h1)93 void prepend(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
94 storeItem(h, h1, OPERATION_PREPEND);
95 }
96
flush(ENGINE_HANDLE * h,ENGINE_HANDLE_V1 * h1)97 void flush(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
98 hasError = h1->flush(h, NULL, 0);
99 }
100
del(ENGINE_HANDLE * h,ENGINE_HANDLE_V1 * h1)101 void del(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
102 hasError = h1->remove(h, NULL, key, strlen(key), 0, 0) != ENGINE_SUCCESS;
103 }
104
set(ENGINE_HANDLE * h,ENGINE_HANDLE_V1 * h1)105 void set(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
106 storeItem(h, h1, OPERATION_SET);
107 }
108
incr(ENGINE_HANDLE * h,ENGINE_HANDLE_V1 * h1)109 void incr(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
110 uint64_t cas;
111 uint64_t result;
112 hasError = h1->arithmetic(h, NULL, key, strlen(key), true, false, 1, 0, expiry,
113 &cas, &result,
114 0) != ENGINE_SUCCESS;
115 }
116
incrWithDefault(ENGINE_HANDLE * h,ENGINE_HANDLE_V1 * h1)117 void incrWithDefault(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
118 uint64_t cas;
119 uint64_t result;
120 hasError = h1->arithmetic(h, NULL, key, strlen(key), true, true, 1, 0, expiry,
121 &cas, &result,
122 0) != ENGINE_SUCCESS;
123 }
124
125
checkValue(ENGINE_HANDLE * h,ENGINE_HANDLE_V1 * h1,const char * exp)126 void checkValue(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1, const char* exp) {
127 item *i = NULL;
128 ENGINE_ERROR_CODE rv = h1->get(h, NULL, &i, key, strlen(key), 0);
129 assert(rv == ENGINE_SUCCESS);
130
131 item_info info;
132 info.nvalue = 1;
133 h1->get_item_info(h, NULL, i, &info);
134
135 char buf[info.value[0].iov_len + 1];
136 memcpy(buf, info.value[0].iov_base, info.value[0].iov_len);
137 buf[sizeof(buf) - 1] = 0x00;
138 assert(info.nvalue == 1);
139 if (strlen(exp) > info.value[0].iov_len) {
140 fprintf(stderr, "Expected at least %d bytes for ``%s'', got %d as ``%s''\n",
141 (int)strlen(exp), exp, (int)info.value[0].iov_len, buf);
142 abort();
143 }
144
145 if (memcmp(info.value[0].iov_base, exp, strlen(exp)) != 0) {
146 fprintf(stderr, "Expected ``%s'', got ``%s''\n", exp, buf);
147 abort();
148 }
149 }
150
assertNotExists(ENGINE_HANDLE * h,ENGINE_HANDLE_V1 * h1)151 void assertNotExists(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1) {
152 item *i;
153 ENGINE_ERROR_CODE rv = h1->get(h, NULL, &i, key, strlen(key), 0);
154 assert(rv == ENGINE_KEY_ENOENT);
155 }
156
157 MEMCACHED_PUBLIC_API
setup_suite(struct test_harness * th)158 bool setup_suite(struct test_harness *th) {
159 testHarness = *th;
160 return true;
161 }
162