static int test_encode(void) { static const enc_vec test_strs[] = { {"hi", "hi"}, {"hi!", "hi%21"}, {"%", "%25"}, {"*", "%2a"}, {"\n", "%0a"}, {"\nhi\n", "%0ahi%0a"} }; static const int num = sizeof(test_strs)/sizeof(enc_vec); int i, ret; char *tmp; ret = TRUE; for (i = 0; i < num; i++) { tmp = hexencode_string(test_strs[i].in); if (!tmp || strcmp(test_strs[i].out, tmp)) { ret = FALSE; tu_dbg("encode failure:\n") tu_dbg("input: \"%s\"\n", test_strs[i].in); tu_dbg("output: \"%s\"\n", tmp? tmp : "(null)"); tu_dbg("expected: \"%s\"\n", test_strs[i].out); } g_free(tmp); } return ret; }
static int test_roundtrip_rand(void) { int i, ret; simpleprng_state_t state; char *in, *tmp_enc = NULL, *tmp_dec = NULL; size_t size; GError *err = NULL; simpleprng_seed(&state, 0xface); ret = TRUE; for (i = 0; i < 100; i++) { size = simpleprng_rand_byte(&state); in = g_malloc0(size+1); simpleprng_fill_buffer(&state, in, size); tmp_enc = hexencode_string(in); tmp_dec = tmp_enc? hexdecode_string(tmp_enc, &err) : NULL; if (!tmp_enc || !tmp_dec || strcmp(in, tmp_dec) || err) { ret = FALSE; tu_dbg("roundtrip failure:\n") tu_dbg("input: \"%s\"\n", in); tu_dbg("enc output: \"%s\"\n", tmp_enc? tmp_enc : "(null)"); tu_dbg("dec output: \"%s\"\n", tmp_dec? tmp_dec : "(null)"); tu_dbg("error msg: %s\n", err? err->message : "(none)"); } g_clear_error(&err); amfree(tmp_enc); amfree(tmp_dec); g_free(in); } return ret; }
static int test_roundtrip(void) { static const round_vec test_strs[] = { "hi", "hi!", "hi%21", "%", "*", "\n", "h%" }; static const int num = sizeof(test_strs)/sizeof(round_vec); int i, ret; char *tmp_enc = NULL, *tmp_dec = NULL; GError *err = NULL; ret = TRUE; for (i = 0; i < num; i++) { tmp_enc = hexencode_string(test_strs[i]); tmp_dec = tmp_enc? hexdecode_string(tmp_enc, &err) : NULL; if (!tmp_enc || !tmp_dec || strcmp(test_strs[i], tmp_dec) || err) { ret = FALSE; tu_dbg("roundtrip failure:\n") tu_dbg("input: \"%s\"\n", test_strs[i]); tu_dbg("enc output: \"%s\"\n", tmp_enc? tmp_enc : "(null)"); tu_dbg("dec output: \"%s\"\n", tmp_dec? tmp_dec : "(null)"); tu_dbg("error msg: %s\n", err? err->message : "(none)"); } g_clear_error(&err); amfree(tmp_enc); amfree(tmp_dec); } return ret; }
static gboolean test_encode(void) { static const enc_vec test_strs[] = { {"hi", "hi"}, {"hi!", "hi%21"}, {"%", "%25"}, {"*", "%2a"}, {"\n", "%0a"}, {"\nhi\n", "%0ahi%0a"} }; static const int num = G_N_ELEMENTS(test_strs); int i; gboolean ret; char *tmp; ret = TRUE; for (i = 0; i < num; i++) { tmp = hexencode_string(test_strs[i].in); if (!tmp || !g_str_equal(test_strs[i].out, tmp)) { ret = FALSE; tu_dbg("encode failure:\n") tu_dbg("input: \"%s\"\n", test_strs[i].in); tu_dbg("output: \"%s\"\n", tmp? tmp : "(null)"); tu_dbg("expected: \"%s\"\n", test_strs[i].out); } g_free(tmp); } return ret; }
static void locking_slave(int in_fd, int out_fd) { char cmd; int rv; file_lock *lock = file_lock_new(TEST_FILENAME); gboolean locked = 0; while (1) { if (!pipeget(in_fd, &cmd)) cmd = 'q'; switch (cmd) { case 'q': /* q = quit */ tu_dbg("slave: quitting\n"); file_lock_free(lock); lock = NULL; return; case 'l': /* l = try locking; reply with 'y' or 'n' */ g_assert(!locked); rv = file_lock_lock(lock); if (rv == -1) { g_fprintf(stderr, "file_lock_lock: %s\n", strerror(errno)); return; } tu_dbg("slave: lock attempt => %s\n", (rv == 1)? "n" : "y"); pipeput(out_fd, (rv == 1)? "n" : "y"); if (rv != 1) locked = 1; break; case 'i': /* i = increment counter, reply with new value */ g_assert(locked); if (!inc_counter(lock)) return; tu_dbg("slave: inc'd to %c\n", lock->data[0]); pipeput(out_fd, lock->data); break; case 'u': /* u = try unlocking; reply with 'k' */ g_assert(locked); rv = file_lock_unlock(lock); if (rv != 0) { g_fprintf(stderr, "file_lock_unlock: %s\n", strerror(errno)); return; } tu_dbg("slave: unlocked\n"); pipeput(out_fd, "k"); locked = 0; break; default: return; } } }
/* Test all amflock implementations available for basic * functionality */ static gboolean test_old_impls(void) { amflock_impl_t **imp = amflock_impls; char *resource = "rez"; int fd; int lock_ro; /* set lnlock's lock directory to the current directory */ extern char *_lnlock_dir; _lnlock_dir = "."; while (*imp) { tu_dbg("Testing amflock-%s\n", (*imp)->impl_name); for (lock_ro = 0; lock_ro < 2; lock_ro++) { /* false (0) or true (1) */ if (unlink(TEST_FILENAME) == -1 && errno != ENOENT) { perror("unlink"); return FALSE; } if ((fd = open(TEST_FILENAME, O_RDWR | O_CREAT | O_EXCL, 0600)) == -1) { perror("open"); return FALSE; } if (lock_ro) { if ((*imp)->amroflock_impl(fd, resource) != 0) { perror("amroflock"); close(fd); return FALSE; } } else { if ((*imp)->amflock_impl(fd, resource) != 0) { perror("amflock"); close(fd); return FALSE; } } if ((*imp)->amfunlock_impl(fd, resource) != 0) { perror("amfunlock"); close(fd); return FALSE; } close(fd); /* ignore error */ unlink(TEST_FILENAME); /* ignore error */ } fprintf(stderr, " PASS amflock-%s\n", (*imp)->impl_name); imp++; } return TRUE; }
static gboolean test_decode(void) { static const dec_vec test_strs[] = { {"hi", "hi", FALSE}, {"hi%21", "hi!", FALSE}, {"%25", "%", FALSE}, {"%2a", "*", FALSE}, {"%2A", "*", FALSE}, {"%0a", "\n", FALSE}, {"%0A", "\n", FALSE}, {"%0ahi%0a", "\nhi\n", FALSE}, {"%", "", TRUE}, {"%2", "", TRUE}, {"h%", "", TRUE}, {"%0h", "", TRUE}, {"%h0", "", TRUE}, {"%00", "", TRUE} }; static const int num = G_N_ELEMENTS(test_strs); int i; gboolean ret; char *tmp; GError *err = NULL; ret = TRUE; for (i = 0; i < num; i++) { tmp = hexdecode_string(test_strs[i].in, &err); if (!tmp || !g_str_equal(test_strs[i].out, tmp) || (!!err != test_strs[i].expect_err)) { ret = FALSE; tu_dbg("decode failure:\n") tu_dbg("input: \"%s\"\n", test_strs[i].in); tu_dbg("output: \"%s\"\n", tmp? tmp : "(null)"); tu_dbg("expected: \"%s\"\n", test_strs[i].out); tu_dbg("error msg: %s\n", err? err->message : "(none)"); } g_clear_error(&err); g_free(tmp); } return ret; }
static int test_sync_parent(ipc_binary_proto_t *proto, int fd) { ipc_binary_channel_t *chan; ipc_binary_message_t *msg; chan = ipc_binary_new_channel(proto); tu_dbg("parent: created channel\n"); msg = ipc_binary_read_message(chan, fd); tu_dbg("parent: read message 1\n"); if (msg->cmd_id != MY_PROTO_CMD1) { tu_dbg("got bad cmd_id %d\n", (int)msg->cmd_id); return 0; } if (msg->args[MY_PROTO_HOSTNAME].data == NULL) { tu_dbg("got NULL hostname\n"); return 0; } if (0 != strcmp((gchar *)msg->args[MY_PROTO_HOSTNAME].data, "localhost")) { tu_dbg("got bad hostname %s\n", (gchar *)msg->args[MY_PROTO_HOSTNAME].data); return 0; } if (msg->args[MY_PROTO_DISK].data != NULL) { tu_dbg("got non-NULL disk\n"); return 0; } ipc_binary_free_message(msg); msg = ipc_binary_read_message(chan, fd); tu_dbg("parent: read message 2\n"); if (msg->cmd_id != MY_PROTO_CMD1) { tu_dbg("got bad cmd_id %d\n", (int)msg->cmd_id); return 0; } if (msg->args[MY_PROTO_HOSTNAME].data == NULL) { tu_dbg("got NULL hostname\n"); return 0; } if (0 != strcmp((gchar *)msg->args[MY_PROTO_HOSTNAME].data, "otherhost")) { tu_dbg("got bad hostname %s\n", (gchar *)msg->args[MY_PROTO_HOSTNAME].data); return 0; } if (msg->args[MY_PROTO_DISK].data == NULL) { tu_dbg("got NULL disk\n"); return 0; } if (0 != strcmp((gchar *)msg->args[MY_PROTO_DISK].data, "/usr")) { tu_dbg("got bad disk %s\n", (gchar *)msg->args[MY_PROTO_DISK].data); return 0; } ipc_binary_free_message(msg); g_usleep(G_USEC_PER_SEC / 8); msg = ipc_binary_read_message(chan, fd); tu_dbg("parent: read message 3\n"); if (msg->cmd_id != MY_PROTO_CMD2) { tu_dbg("got bad cmd_id %d\n", (int)msg->cmd_id); return 0; } if (msg->args[MY_PROTO_DATA].data == NULL) { tu_dbg("got NULL data\n"); return 0; } if (msg->args[MY_PROTO_DATA].len != 9) { tu_dbg("got data length %d, expected 9\n", (int)msg->args[MY_PROTO_DATA].len); return 0; } if (0 != strncmp((gchar *)msg->args[MY_PROTO_DATA].data, "some-data", 9)) { tu_dbg("got bad data\n"); return 0; } ipc_binary_free_message(msg); return 1; }
static int locking_master(int in_fd, int out_fd) { file_lock *lock = file_lock_new(TEST_FILENAME); int rv; char slaveres; /* start by locking here and incrementing the value */ rv = file_lock_lock(lock); if (rv == -1) { g_fprintf(stderr, "file_lock_lock: %s\n", strerror(errno)); return 0; } g_assert(rv != 1); /* not already locked */ tu_dbg("master: locked\n"); if (!inc_counter(lock)) return 0; g_assert(lock->data[0] == 'b'); tu_dbg("master: inc'd to b\n"); /* unlock and re-lock */ rv = file_lock_unlock(lock); if (rv != 0) { g_fprintf(stderr, "file_lock_unlock: %s\n", strerror(errno)); return 0; } tu_dbg("master: unlocked\n"); rv = file_lock_lock(lock); if (rv == -1) { g_fprintf(stderr, "file_lock_lock: %s\n", strerror(errno)); return 0; } g_assert(rv != 1); /* not already locked */ tu_dbg("master: locked\n"); /* inc it again */ g_assert(lock->data[0] == 'b'); inc_counter(lock); g_assert(lock->data[0] == 'c'); tu_dbg("master: inc'd to c\n"); /* the slave should fail to get a lock now */ pipeput(out_fd, "l"); g_assert(pipeget(in_fd, &slaveres)); g_assert(slaveres == 'n'); /* and, finally unlock */ rv = file_lock_unlock(lock); if (rv != 0) { g_fprintf(stderr, "file_lock_unlock: %s\n", strerror(errno)); return 0; } tu_dbg("master: unlocked\n"); /* the slave should succeed now */ pipeput(out_fd, "l"); g_assert(pipeget(in_fd, &slaveres)); g_assert(slaveres == 'y'); pipeput(out_fd, "i"); g_assert(pipeget(in_fd, &slaveres)); g_assert(slaveres == 'd'); /* master shouldn't be able to lock now */ rv = file_lock_lock(lock); if (rv == -1) { g_fprintf(stderr, "file_lock_lock: %s\n", strerror(errno)); return 0; } g_assert(rv == 1); /* already locked */ tu_dbg("master: lock attempt failed (as expected)\n"); pipeput(out_fd, "i"); g_assert(pipeget(in_fd, &slaveres)); g_assert(slaveres == 'e'); /* get the slave to unlock */ pipeput(out_fd, "u"); g_assert(pipeget(in_fd, &slaveres)); g_assert(slaveres == 'k'); /* we should get a lock now */ rv = file_lock_lock(lock); if (rv == -1) { g_fprintf(stderr, "file_lock_lock: %s\n", strerror(errno)); return 0; } g_assert(rv != 1); /* not already locked */ tu_dbg("master: lock attempt succeeded\n"); g_assert(lock->data[0] == 'e'); /* leave it unlocked, just to see what happens */ return 1; }