1 /* 2 protocol tests 3 4 Copyright (C) Amitay Isaacs 2015 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include <assert.h> 21 22 #include "protocol/protocol_basic.c" 23 #include "protocol/protocol_types.c" 24 #include "protocol/protocol_header.c" 25 #include "protocol/protocol_call.c" 26 #include "protocol/protocol_control.c" 27 #include "protocol/protocol_message.c" 28 #include "protocol/protocol_keepalive.c" 29 #include "protocol/protocol_tunnel.c" 30 #include "protocol/protocol_packet.c" 31 32 #include "tests/src/protocol_common.h" 33 #include "tests/src/protocol_common_ctdb.h" 34 35 /* 36 * Functions to test marshalling 37 */ 38 39 /* for ctdb_req_header */ 40 #define PROTOCOL_CTDB1_TEST(TYPE, NAME) \ 41 static void TEST_FUNC(NAME)(void) \ 42 { \ 43 TALLOC_CTX *mem_ctx; \ 44 TYPE c1, c2; \ 45 uint8_t *pkt; \ 46 size_t pkt_len, buflen, np; \ 47 int ret; \ 48 \ 49 printf("%s\n", #NAME); \ 50 fflush(stdout); \ 51 mem_ctx = talloc_new(NULL); \ 52 assert(mem_ctx != NULL); \ 53 FILL_FUNC(NAME)(&c1); \ 54 buflen = LEN_FUNC(NAME)(&c1); \ 55 ret = ctdb_allocate_pkt(mem_ctx, buflen, &pkt, &pkt_len); \ 56 assert(ret == 0); \ 57 assert(pkt != NULL); \ 58 assert(pkt_len >= buflen); \ 59 np = 0; \ 60 PUSH_FUNC(NAME)(&c1, pkt, &np); \ 61 assert(np == buflen); \ 62 np = 0; \ 63 ret = PULL_FUNC(NAME)(pkt, pkt_len, &c2, &np); \ 64 assert(ret == 0); \ 65 assert(np == buflen); \ 66 VERIFY_FUNC(NAME)(&c1, &c2); \ 67 talloc_free(mem_ctx); \ 68 } 69 70 /* for ctdb_req_control_data, ctdb_reply_control_data */ 71 #define PROTOCOL_CTDB2_TEST(TYPE, NAME) \ 72 static void TEST_FUNC(NAME)(uint32_t opcode) \ 73 { \ 74 TALLOC_CTX *mem_ctx; \ 75 TYPE c1, c2; \ 76 uint8_t *pkt; \ 77 size_t pkt_len, buflen, np; \ 78 int ret; \ 79 \ 80 printf("%s %u\n", #NAME, opcode); \ 81 fflush(stdout); \ 82 mem_ctx = talloc_new(NULL); \ 83 assert(mem_ctx != NULL); \ 84 FILL_FUNC(NAME)(mem_ctx, &c1, opcode); \ 85 buflen = LEN_FUNC(NAME)(&c1); \ 86 ret = ctdb_allocate_pkt(mem_ctx, buflen, &pkt, &pkt_len); \ 87 assert(ret == 0); \ 88 assert(pkt != NULL); \ 89 assert(pkt_len >= buflen); \ 90 np = 0; \ 91 PUSH_FUNC(NAME)(&c1, pkt, &np); \ 92 assert(np == buflen); \ 93 np = 0; \ 94 ret = PULL_FUNC(NAME)(pkt, pkt_len, opcode, mem_ctx, &c2, &np); \ 95 assert(ret == 0); \ 96 assert(np == buflen); \ 97 VERIFY_FUNC(NAME)(&c1, &c2); \ 98 talloc_free(mem_ctx); \ 99 } 100 101 /* for ctdb_message_data */ 102 #define PROTOCOL_CTDB3_TEST(TYPE, NAME) \ 103 static void TEST_FUNC(NAME)(uint64_t srvid) \ 104 { \ 105 TALLOC_CTX *mem_ctx; \ 106 TYPE c1, c2; \ 107 uint8_t *pkt; \ 108 size_t pkt_len, buflen, np; \ 109 int ret; \ 110 \ 111 printf("%s %"PRIx64"\n", #NAME, srvid); \ 112 fflush(stdout); \ 113 mem_ctx = talloc_new(NULL); \ 114 assert(mem_ctx != NULL); \ 115 FILL_FUNC(NAME)(mem_ctx, &c1, srvid); \ 116 buflen = LEN_FUNC(NAME)(&c1, srvid); \ 117 ret = ctdb_allocate_pkt(mem_ctx, buflen, &pkt, &pkt_len); \ 118 assert(ret == 0); \ 119 assert(pkt != NULL); \ 120 assert(pkt_len >= buflen); \ 121 np = 0; \ 122 PUSH_FUNC(NAME)(&c1, srvid, pkt, &np); \ 123 assert(np == buflen); \ 124 np = 0; \ 125 ret = PULL_FUNC(NAME)(pkt, pkt_len, srvid, mem_ctx, &c2, &np); \ 126 assert(ret == 0); \ 127 assert(np == buflen); \ 128 VERIFY_FUNC(NAME)(&c1, &c2, srvid); \ 129 talloc_free(mem_ctx); \ 130 } 131 132 /* for ctdb_req_call, ctdb_reply_call, etc. */ 133 #define PROTOCOL_CTDB4_TEST(TYPE, NAME, OPER) \ 134 static void TEST_FUNC(NAME)(void) \ 135 { \ 136 TALLOC_CTX *mem_ctx; \ 137 struct ctdb_req_header h1, h2; \ 138 TYPE c1, c2; \ 139 uint8_t *pkt; \ 140 size_t pkt_len, buflen, len; \ 141 int ret; \ 142 \ 143 printf("%s\n", #NAME); \ 144 fflush(stdout); \ 145 mem_ctx = talloc_new(NULL); \ 146 assert(mem_ctx != NULL); \ 147 fill_ctdb_req_header(&h1); \ 148 FILL_FUNC(NAME)(mem_ctx, &c1); \ 149 buflen = LEN_FUNC(NAME)(&h1, &c1); \ 150 ret = ctdb_allocate_pkt(mem_ctx, buflen, &pkt, &pkt_len); \ 151 assert(ret == 0); \ 152 assert(pkt != NULL); \ 153 assert(pkt_len >= buflen); \ 154 len = 0; \ 155 ret = PUSH_FUNC(NAME)(&h1, &c1, pkt, &len); \ 156 assert(ret == EMSGSIZE); \ 157 assert(len == buflen); \ 158 ret = PUSH_FUNC(NAME)(&h1, &c1, pkt, &pkt_len); \ 159 assert(ret == 0); \ 160 ret = PULL_FUNC(NAME)(pkt, pkt_len, &h2, mem_ctx, &c2); \ 161 assert(ret == 0); \ 162 verify_ctdb_req_header(&h1, &h2); \ 163 assert(h2.length == pkt_len); \ 164 VERIFY_FUNC(NAME)(&c1, &c2); \ 165 talloc_free(mem_ctx); \ 166 } 167 168 /* for ctdb_req_control */ 169 #define PROTOCOL_CTDB5_TEST(TYPE, NAME, OPER) \ 170 static void TEST_FUNC(NAME)(uint32_t opcode) \ 171 { \ 172 TALLOC_CTX *mem_ctx; \ 173 struct ctdb_req_header h1, h2; \ 174 TYPE c1, c2; \ 175 uint8_t *pkt; \ 176 size_t pkt_len, buflen, len; \ 177 int ret; \ 178 \ 179 printf("%s %u\n", #NAME, opcode); \ 180 fflush(stdout); \ 181 mem_ctx = talloc_new(NULL); \ 182 assert(mem_ctx != NULL); \ 183 fill_ctdb_req_header(&h1); \ 184 FILL_FUNC(NAME)(mem_ctx, &c1, opcode); \ 185 buflen = LEN_FUNC(NAME)(&h1, &c1); \ 186 ret = ctdb_allocate_pkt(mem_ctx, buflen, &pkt, &pkt_len); \ 187 assert(ret == 0); \ 188 assert(pkt != NULL); \ 189 assert(pkt_len >= buflen); \ 190 len = 0; \ 191 ret = PUSH_FUNC(NAME)(&h1, &c1, pkt, &len); \ 192 assert(ret == EMSGSIZE); \ 193 assert(len == buflen); \ 194 ret = PUSH_FUNC(NAME)(&h1, &c1, pkt, &pkt_len); \ 195 assert(ret == 0); \ 196 ret = PULL_FUNC(NAME)(pkt, pkt_len, &h2, mem_ctx, &c2); \ 197 assert(ret == 0); \ 198 verify_ctdb_req_header(&h1, &h2); \ 199 assert(h2.length == pkt_len); \ 200 VERIFY_FUNC(NAME)(&c1, &c2); \ 201 talloc_free(mem_ctx); \ 202 } 203 204 /* for ctdb_reply_control */ 205 #define PROTOCOL_CTDB6_TEST(TYPE, NAME, OPER) \ 206 static void TEST_FUNC(NAME)(uint32_t opcode) \ 207 { \ 208 TALLOC_CTX *mem_ctx; \ 209 struct ctdb_req_header h1, h2; \ 210 TYPE c1, c2; \ 211 uint8_t *pkt; \ 212 size_t pkt_len, buflen, len; \ ctdb_req_header_len_old(struct ctdb_req_header * in)213 int ret; \ 214 \ 215 printf("%s %u\n", #NAME, opcode); \ 216 fflush(stdout); \ 217 mem_ctx = talloc_new(NULL); \ ctdb_req_header_push_old(struct ctdb_req_header * in,uint8_t * buf)218 assert(mem_ctx != NULL); \ 219 fill_ctdb_req_header(&h1); \ 220 FILL_FUNC(NAME)(mem_ctx, &c1, opcode); \ 221 buflen = LEN_FUNC(NAME)(&h1, &c1); \ 222 ret = ctdb_allocate_pkt(mem_ctx, buflen, &pkt, &pkt_len); \ ctdb_req_header_pull_old(uint8_t * buf,size_t buflen,struct ctdb_req_header * out)223 assert(ret == 0); \ 224 assert(pkt != NULL); \ 225 assert(pkt_len >= buflen); \ 226 len = 0; \ 227 ret = PUSH_FUNC(NAME)(&h1, &c1, pkt, &len); \ 228 assert(ret == EMSGSIZE); \ 229 assert(len == buflen); \ 230 ret = PUSH_FUNC(NAME)(&h1, &c1, pkt, &pkt_len); \ 231 assert(ret == 0); \ 232 ret = PULL_FUNC(NAME)(pkt, pkt_len, opcode, &h2, mem_ctx, &c2); \ 233 assert(ret == 0); \ 234 verify_ctdb_req_header(&h1, &h2); \ 235 assert(h2.length == pkt_len); \ 236 VERIFY_FUNC(NAME)(&c1, &c2); \ 237 talloc_free(mem_ctx); \ 238 } 239 240 /* for ctdb_req_message */ 241 #define PROTOCOL_CTDB7_TEST(TYPE, NAME, OPER) \ 242 static void TEST_FUNC(NAME)(uint64_t srvid) \ 243 { \ 244 TALLOC_CTX *mem_ctx; \ ctdb_req_call_len_old(struct ctdb_req_header * h,struct ctdb_req_call * c)245 struct ctdb_req_header h1, h2; \ 246 TYPE c1, c2; \ 247 uint8_t *pkt; \ 248 size_t pkt_len, buflen, len; \ 249 int ret; \ 250 \ 251 printf("%s %"PRIx64"\n", #NAME, srvid); \ 252 fflush(stdout); \ ctdb_req_call_push_old(struct ctdb_req_header * h,struct ctdb_req_call * c,uint8_t * buf,size_t * buflen)253 mem_ctx = talloc_new(NULL); \ 254 assert(mem_ctx != NULL); \ 255 fill_ctdb_req_header(&h1); \ 256 FILL_FUNC(NAME)(mem_ctx, &c1, srvid); \ 257 buflen = LEN_FUNC(NAME)(&h1, &c1); \ 258 ret = ctdb_allocate_pkt(mem_ctx, buflen, &pkt, &pkt_len); \ 259 assert(ret == 0); \ 260 assert(pkt != NULL); \ 261 assert(pkt_len >= buflen); \ 262 len = 0; \ 263 ret = PUSH_FUNC(NAME)(&h1, &c1, pkt, &len); \ 264 assert(ret == EMSGSIZE); \ 265 assert(len == buflen); \ 266 ret = PUSH_FUNC(NAME)(&h1, &c1, pkt, &pkt_len); \ 267 assert(ret == 0); \ 268 ret = PULL_FUNC(NAME)(pkt, pkt_len, &h2, mem_ctx, &c2); \ 269 assert(ret == 0); \ 270 verify_ctdb_req_header(&h1, &h2); \ 271 assert(h2.length == pkt_len); \ 272 VERIFY_FUNC(NAME)(&c1, &c2); \ 273 talloc_free(mem_ctx); \ 274 } 275 276 PROTOCOL_CTDB1_TEST(struct ctdb_req_header, ctdb_req_header); 277 278 PROTOCOL_CTDB4_TEST(struct ctdb_req_call, ctdb_req_call, CTDB_REQ_CALL); 279 PROTOCOL_CTDB4_TEST(struct ctdb_reply_call, ctdb_reply_call, CTDB_REPLY_CALL); 280 PROTOCOL_CTDB4_TEST(struct ctdb_reply_error, ctdb_reply_error, 281 CTDB_REPLY_ERROR); 282 PROTOCOL_CTDB4_TEST(struct ctdb_req_dmaster, ctdb_req_dmaster, 283 CTDB_REQ_DMASTER); 284 PROTOCOL_CTDB4_TEST(struct ctdb_reply_dmaster, ctdb_reply_dmaster, 285 CTDB_REPLY_DMASTER); ctdb_req_call_pull_old(uint8_t * buf,size_t buflen,struct ctdb_req_header * h,TALLOC_CTX * mem_ctx,struct ctdb_req_call * c)286 287 #define NUM_CONTROLS 156 288 289 PROTOCOL_CTDB2_TEST(struct ctdb_req_control_data, ctdb_req_control_data); 290 PROTOCOL_CTDB2_TEST(struct ctdb_reply_control_data, ctdb_reply_control_data); 291 292 PROTOCOL_CTDB5_TEST(struct ctdb_req_control, ctdb_req_control, 293 CTDB_REQ_CONTROL); 294 PROTOCOL_CTDB6_TEST(struct ctdb_reply_control, ctdb_reply_control, 295 CTDB_REPLY_CONTROL); 296 297 PROTOCOL_CTDB3_TEST(union ctdb_message_data, ctdb_message_data); 298 PROTOCOL_CTDB7_TEST(struct ctdb_req_message, ctdb_req_message, 299 CTDB_REQ_MESSAGE); 300 PROTOCOL_CTDB4_TEST(struct ctdb_req_message_data, ctdb_req_message_data, 301 CTDB_REQ_MESSAGE); 302 303 PROTOCOL_CTDB4_TEST(struct ctdb_req_keepalive, ctdb_req_keepalive, 304 CTDB_REQ_KEEPALIVE); 305 PROTOCOL_CTDB4_TEST(struct ctdb_req_tunnel, ctdb_req_tunnel, CTDB_REQ_TUNNEL); 306 307 int main(int argc, char *argv[]) 308 { 309 uint32_t opcode; 310 uint64_t test_srvid[] = { 311 CTDB_SRVID_BANNING, 312 CTDB_SRVID_ELECTION, 313 CTDB_SRVID_RECONFIGURE, 314 CTDB_SRVID_RELEASE_IP, 315 CTDB_SRVID_TAKE_IP, 316 CTDB_SRVID_SET_NODE_FLAGS, 317 CTDB_SRVID_RECD_UPDATE_IP, 318 CTDB_SRVID_VACUUM_FETCH, 319 CTDB_SRVID_DETACH_DATABASE, 320 CTDB_SRVID_MEM_DUMP, 321 CTDB_SRVID_GETLOG, 322 CTDB_SRVID_CLEARLOG, 323 CTDB_SRVID_PUSH_NODE_FLAGS, 324 CTDB_SRVID_RELOAD_NODES, 325 CTDB_SRVID_TAKEOVER_RUN, 326 CTDB_SRVID_REBALANCE_NODE, 327 CTDB_SRVID_DISABLE_TAKEOVER_RUNS, 328 CTDB_SRVID_DISABLE_RECOVERIES, 329 CTDB_SRVID_DISABLE_IP_CHECK, 330 }; 331 size_t i; 332 333 if (argc == 2) { 334 int seed = atoi(argv[1]); 335 srandom(seed); 336 } 337 338 TEST_FUNC(ctdb_req_header)(); 339 340 TEST_FUNC(ctdb_req_call)(); 341 TEST_FUNC(ctdb_reply_call)(); 342 TEST_FUNC(ctdb_reply_error)(); 343 TEST_FUNC(ctdb_req_dmaster)(); 344 TEST_FUNC(ctdb_reply_dmaster)(); 345 346 for (opcode=0; opcode<NUM_CONTROLS; opcode++) { 347 TEST_FUNC(ctdb_req_control_data)(opcode); ctdb_reply_call_len_old(struct ctdb_req_header * h,struct ctdb_reply_call * c)348 } 349 for (opcode=0; opcode<NUM_CONTROLS; opcode++) { 350 TEST_FUNC(ctdb_reply_control_data)(opcode); 351 } 352 353 for (opcode=0; opcode<NUM_CONTROLS; opcode++) { 354 TEST_FUNC(ctdb_req_control)(opcode); ctdb_reply_call_push_old(struct ctdb_req_header * h,struct ctdb_reply_call * c,uint8_t * buf,size_t * buflen)355 } 356 for (opcode=0; opcode<NUM_CONTROLS; opcode++) { 357 TEST_FUNC(ctdb_reply_control)(opcode); 358 } 359 360 for (i=0; i<ARRAY_SIZE(test_srvid); i++) { 361 TEST_FUNC(ctdb_message_data)(test_srvid[i]); 362 } 363 for (i=0; i<ARRAY_SIZE(test_srvid); i++) { 364 TEST_FUNC(ctdb_req_message)(test_srvid[i]); 365 } 366 TEST_FUNC(ctdb_req_message_data)(); 367 368 TEST_FUNC(ctdb_req_keepalive)(); 369 TEST_FUNC(ctdb_req_tunnel)(); 370 371 return 0; 372 } 373