/* * client_send_disconnect -- connect, send specified number of bytes and * disconnect */ static void client_send_disconnect(char *target, void *msg, size_t size) { struct rpmem_ssh *ssh = clnt_connect(target); if (size) clnt_send(ssh, msg, size); clnt_close(ssh); }
/* * client_msg_close_noresp -- send close request message and don't expect a * response */ static void client_msg_close_noresp(const char *ctarget) { char *target = STRDUP(ctarget); struct rpmem_msg_close msg = CLOSE_MSG; rpmem_hton_msg_close(&msg); int fd = clnt_connect_wait(target); clnt_send(fd, &msg, sizeof(msg)); clnt_wait_disconnect(fd); clnt_close(fd); FREE(target); }
/* * client_bad_msg_hdr -- test case for checking message header */ int client_bad_msg_hdr(const struct test_case *tc, int argc, char *argv[]) { if (argc < 1) UT_FATAL("usage: %s <addr>[:<port>]", tc->name); char *target = argv[0]; set_rpmem_cmd("server_bad_msg"); for (int i = 0; i < BAD_MSG_HDR_COUNT; i++) { struct rpmem_ssh *ssh = clnt_connect(target); struct rpmem_msg_hdr msg = MSG_HDR; switch (i) { case 0: msg.size -= 1; break; case 1: msg.size = 0; break; case 2: msg.type = MAX_RPMEM_MSG_TYPE; break; case 3: msg.type = RPMEM_MSG_TYPE_OPEN_RESP; break; case 4: msg.type = RPMEM_MSG_TYPE_CREATE_RESP; break; case 5: msg.type = RPMEM_MSG_TYPE_CLOSE_RESP; break; default: UT_ASSERT(0); } rpmem_hton_msg_hdr(&msg); clnt_send(ssh, &msg, sizeof(msg)); clnt_wait_disconnect(ssh); clnt_close(ssh); } return 1; }
/* * client_msg_close_resp -- send close request message and expect a response * with specified status. If status is 0, validate close request response * message */ static void client_msg_close_resp(const char *ctarget, int status) { char *target = STRDUP(ctarget); struct rpmem_msg_close msg = CLOSE_MSG; rpmem_hton_msg_close(&msg); struct rpmem_msg_close_resp resp; int fd = clnt_connect_wait(target); clnt_send(fd, &msg, sizeof(msg)); clnt_recv(fd, &resp, sizeof(resp)); rpmem_ntoh_msg_close_resp(&resp); if (status) UT_ASSERTeq(resp.hdr.status, (uint32_t)status); clnt_close(fd); FREE(target); }
/* * client_msg_open_noresp -- send open request message and don't expect a * response */ static void client_msg_open_noresp(const char *ctarget) { char *target = STRDUP(ctarget); size_t msg_size = sizeof(OPEN_MSG) + POOL_DESC_SIZE; struct rpmem_msg_open *msg = MALLOC(msg_size); int fd = clnt_connect_wait(target); *msg = OPEN_MSG; msg->hdr.size = msg_size; memcpy(msg->pool_desc.desc, POOL_DESC, POOL_DESC_SIZE); rpmem_hton_msg_open(msg); clnt_send(fd, msg, msg_size); clnt_wait_disconnect(fd); clnt_close(fd); FREE(msg); FREE(target); }
/* * client_msg_open_resp -- send open request message and expect a response * with specified status. If status is 0, validate open request response * message */ static void client_msg_open_resp(const char *ctarget, int status) { char *target = STRDUP(ctarget); size_t msg_size = sizeof(OPEN_MSG) + POOL_DESC_SIZE; struct rpmem_msg_open *msg = MALLOC(msg_size); struct rpmem_msg_open_resp resp; int fd = clnt_connect_wait(target); *msg = OPEN_MSG; msg->hdr.size = msg_size; memcpy(msg->pool_desc.desc, POOL_DESC, POOL_DESC_SIZE); rpmem_hton_msg_open(msg); clnt_send(fd, msg, msg_size); clnt_recv(fd, &resp, sizeof(resp)); rpmem_ntoh_msg_open_resp(&resp); if (status) { UT_ASSERTeq(resp.hdr.status, (uint32_t)status); } else { UT_ASSERTeq(resp.hdr.type, RPMEM_MSG_TYPE_OPEN_RESP); UT_ASSERTeq(resp.hdr.size, sizeof(struct rpmem_msg_open_resp)); UT_ASSERTeq(resp.hdr.status, (uint32_t)status); UT_ASSERTeq(resp.ibc.port, PORT); UT_ASSERTeq(resp.ibc.rkey, RKEY); UT_ASSERTeq(resp.ibc.raddr, RADDR); UT_ASSERTeq(resp.ibc.persist_method, PERSIST_METHOD); } clnt_close(fd); FREE(msg); FREE(target); }
/* * client_bad_msg_open -- check if server detects invalid open request * messages */ static void client_bad_msg_open(const char *ctarget) { char *target = STRDUP(ctarget); size_t msg_size = sizeof(OPEN_MSG) + POOL_DESC_SIZE; struct rpmem_msg_open *msg = MALLOC(msg_size); for (int i = 0; i < BAD_MSG_OPEN_COUNT; i++) { int fd = clnt_connect_wait(target); *msg = OPEN_MSG; msg->hdr.size = msg_size; memcpy(msg->pool_desc.desc, POOL_DESC, POOL_DESC_SIZE); switch (i) { case 0: msg->provider = 0; break; case 1: msg->provider = MAX_RPMEM_PROV; break; case 2: msg->pool_desc.size -= 1; break; case 3: msg->pool_desc.size += 1; break; case 4: msg->pool_desc.size = 0; msg->hdr.size = sizeof(OPEN_MSG) + msg->pool_desc.size; break; case 5: msg->pool_desc.size = 1; msg->hdr.size = sizeof(OPEN_MSG) + msg->pool_desc.size; break; case 6: msg->pool_desc.desc[0] = '\0'; break; case 7: msg->pool_desc.desc[POOL_DESC_SIZE / 2] = '\0'; break; case 8: msg->pool_desc.desc[POOL_DESC_SIZE - 1] = 'E'; break; case 9: msg->major = RPMEM_PROTO_MAJOR + 1; break; case 10: msg->minor = RPMEM_PROTO_MINOR + 1; break; default: UT_ASSERT(0); } rpmem_hton_msg_open(msg); clnt_send(fd, msg, msg_size); clnt_wait_disconnect(fd); clnt_close(fd); } FREE(msg); FREE(target); }
int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage: %s <1|2|3> (for test case 1, 2, or 3)\n", argv[0]); return -1; } int testcase = atoi(argv[1]); int i, j; struct host_t *server = clnt_conn(SERVER, PORT); struct file_t *file; char *p; if( !server ) { printf("Error! Cannot connect to server.\n"); return -1; } switch (testcase) { case 1: /* Open file A, write static string, close file. */ /* Open file A, read data into 2nd buffer and verify correctness. */ /* Assume A.txt contains 1024 A's */ if( !(file = clnt_open(server, "A.txt")) ) { printf("Error! Cannot open file!\n"); return -1; } if( clnt_write(file, 0, 'c') < 0 || clnt_write(file, 1, 's') < 0 || clnt_write(file, 2, '5') < 0 || clnt_write(file, 3, '2') < 0 || clnt_write(file, 4, '7') < 0) { printf("Error writing data to file!\n"); return -1; } clnt_close(server, file, SAVE); if( !(file = clnt_open(server, "A.txt")) ) { printf("Error! Cannot open file!\n"); return -1; } p = (char*)malloc(16*sizeof(char)); if( (clnt_read(file, p, 0, 16) != 4) ) { printf("Error! Null pointer from read block!\n"); return -1; } if( p[0] == 'c' && p[1] == 's' && p[2] == '5' && p[3] == '2' && p[4] == '7' && p[5] == 'A') { for(i=6; i<16; ++i) { if(p[i] != 'A') { printf("Error reading expected 'A's in #%d\n", testcase); break; } } if( i == BLOCK_SIZE ) printf("Testcase #%d correct!\n", testcase); } else printf("Testcase #%d Wrong.\n", testcase); clnt_close(server, file, DONTSAVE); clnt_term(server); free(p); break; case 2: /* Open file A, write data to it, close it. */ /* Open file A, read data into buffer, close it. */ /* Create new file B, write buffer to file B, close it. */ /* Open file B, verify correctness of written data. */ /* Assume B.txt contain 20 B's */ if( !(file = clnt_open(server, "B.txt")) ) { printf("Error! Cannot open file!\n"); return -1; } p = (char*)malloc(20*sizeof(char)); if( (clnt_read(file, p, 3, 20) != 17) ) { printf("Error: wrong size of B!\n"); return -1; } for(i=0; i<17; ++i) { if(p[i] != 'B') { printf("Testcase #%d wrong.\n", testcase); break; } } clnt_close(server, file, DONTSAVE); free(p); /* Assume C.txt doesn't exists */ if( !(file = clnt_open(server, "C.txt")) ) { printf("Error! Cannot open file!\n"); return -1; } p = (char*)malloc(256*sizeof(char)); if( (clnt_read(file, p, 0, 10) != 0) ) { printf("Error read unexpected data!\n"); return -1; } for(i=0; i<1337; ++i) { if( clnt_write(file, i, 'K') < 0 ) { printf("Error! Cannot write to file!\n"); return -1; } } clnt_close(server, file, SAVE); if( !(file = clnt_open(server, "C.txt")) ) { printf("Error! Cannot open file!\n"); return -1; } if( (clnt_read(file, p, 0, 256) != 256) ) { printf("Error unepxected read!\n"); return -1; } for(i=0; i<256; ++i) { if(p[i] != 'K') { printf("Testcase #%d Wrong.\n", testcase); break; } } if( (clnt_read(file, p, 512, 256) != 256) ) { printf("Error unexpected read!\n"); return -1; } for(i=0; i<256; ++i) { if(p[i] != 'K') { printf("Testcase #%d Wrong.\n", testcase); break; } } clnt_close(server, file, DONTSAVE); clnt_term(server); free(p); printf("Testcase #%d Correct!\n", testcase); break; case 3: /* Longer testcase that switches between OPEN/READ/WRITE/EDIT */ /* D contains 60 D's */ if( !(file = clnt_open(server, "D.txt")) ) { printf("Error! Cannot open file!\n"); return -1; } /* should return 1st block */ p = (char*)malloc(200*sizeof(char)); if( (clnt_read(file, p, 10, 200) != 50) ) { printf("Error, unexpected read!\n"); return -1; } for(i=0; i<999999; ++i) { if( clnt_write(file, i, 'X') < 0 ) { printf("Error! Cannot write to file!\n"); return -1; } } clnt_close(server, file, DONTSAVE); /* D still contains 60 D's */ if( !(file = clnt_open(server, "D.txt")) ) { printf("Error! Cannot open file!\n"); return -1; } /* should return 1st block */ if( (clnt_read(file, p, 50, 200) != 10) ) { printf("Error, unexpected read!\n"); return -1; } for(i=0; i<10; ++i) if(p[i] != 'D') { printf("Testcase #%d Wrong.\n", testcase); break; } clnt_close(server, file, DONTSAVE); if( !(file = clnt_open(server, "D.txt")) ) { printf("Error! Cannot open file!\n"); return -1; } /* should return 1st block */ if( clnt_read(file, p, 0, 200) != 60 ) { printf("Error, unexpected read!\n"); return -1; } for(i=0; i<999999; ++i) if( clnt_write(file, i, 'X') < 0 ) { printf("Error! Cannot open file!\n"); return -1; } clnt_close(server, file, SAVE); /* D contains Xs */ if( !(file = clnt_open(server, "D.txt")) ) { printf("Error! Cannot open file!\n"); return -1; } for(j=0; j<20; j++) { if( clnt_read(file, p, j*200, 200) != 200) { printf("Error, unexpected read!\n"); return -1; } for(i=0; i<200; ++i) { if(p[i] != 'X') { printf("Testcase #%d Wrong.\n", testcase); return -1; } } } clnt_close(server, file, DONTSAVE); clnt_term(server); free(p); printf("Testcase #%d Correct!\n", testcase); break; default: printf("Illegal test case.\n"); } }