#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <test.h>
#define PING_S1 0
#define PING_S2 1
struct ping_task {
int state;
test_string_t arg;
test_string_t read_result;
exports_test_future_string_t future;
test_waitable_set_t set;
exports_test_future_string_writer_t writer;
};
test_callback_code_t exports_test_ping(exports_test_future_string_t x, test_string_t *y) {
struct ping_task *task = (struct ping_task*) malloc(sizeof(struct ping_task));
assert(task != NULL);
memset(task, 0, sizeof(struct ping_task));
task->state = PING_S1;
task->arg = *y;
task->future = x;
task->set = test_waitable_set_new();
test_waitable_status_t status = exports_test_future_string_read(x, &task->read_result);
assert(status == TEST_WAITABLE_STATUS_BLOCKED);
test_waitable_join(task->future, task->set);
test_context_set_0(task);
return TEST_CALLBACK_CODE_WAIT(task->set);
}
test_callback_code_t exports_test_ping_callback(test_event_t *event) {
struct ping_task *task = (struct ping_task*) test_context_get_0();
switch (task->state) {
case PING_S1: {
assert(event->event == TEST_EVENT_FUTURE_READ);
assert(event->waitable == task->future);
assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_COMPLETED);
assert(TEST_WAITABLE_COUNT(event->code) == 0);
test_waitable_join(task->future, 0);
exports_test_future_string_drop_readable(task->future);
task->future = 0;
exports_test_future_string_writer_t writer;
exports_test_future_string_t reader = exports_test_future_string_new(&writer);
exports_test_ping_return(reader);
task->writer = writer;
test_string_t concatenated;
concatenated.len = task->arg.len + task->read_result.len;
concatenated.ptr = (uint8_t*) malloc(concatenated.len);
assert(concatenated.ptr != NULL);
memcpy(concatenated.ptr, task->read_result.ptr, task->read_result.len);
memcpy(concatenated.ptr + task->read_result.len, task->arg.ptr, task->arg.len);
test_string_free(&task->arg);
test_string_free(&task->read_result);
task->arg = concatenated;
test_waitable_status_t status = exports_test_future_string_write(writer, &task->arg);
assert(status == TEST_WAITABLE_STATUS_BLOCKED);
task->state = PING_S2;
test_waitable_join(writer, task->set);
return TEST_CALLBACK_CODE_WAIT(task->set);
}
case PING_S2: {
assert(event->event == TEST_EVENT_FUTURE_WRITE);
assert(event->waitable == task->writer);
assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_COMPLETED);
assert(TEST_WAITABLE_COUNT(event->code) == 0);
test_waitable_join(task->writer, 0);
exports_test_future_string_drop_writable(task->writer);
task->writer = 0;
test_waitable_set_drop(task->set);
task->set = 0;
test_string_free(&task->arg);
free(task);
return TEST_CALLBACK_CODE_EXIT;
}
default:
assert(0);
}
}
struct pong_task {
test_string_t read_result;
exports_test_future_string_t future;
test_waitable_set_t set;
};
test_callback_code_t exports_test_pong(exports_test_future_string_t x) {
struct pong_task *task = (struct pong_task*) malloc(sizeof(struct pong_task));
assert(task != NULL);
task->future = x;
task->set = test_waitable_set_new();
test_waitable_status_t status = exports_test_future_string_read(x, &task->read_result);
assert(status == TEST_WAITABLE_STATUS_BLOCKED);
test_waitable_join(task->future, task->set);
test_context_set_0(task);
return TEST_CALLBACK_CODE_WAIT(task->set);
}
test_callback_code_t exports_test_pong_callback(test_event_t *event) {
struct pong_task *task = (struct pong_task*) test_context_get_0();
assert(event->event == TEST_EVENT_FUTURE_READ);
assert(event->waitable == task->future);
assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_COMPLETED);
assert(TEST_WAITABLE_COUNT(event->code) == 0);
test_waitable_join(task->future, 0);
exports_test_future_string_drop_readable(task->future);
task->future = 0;
test_waitable_set_drop(task->set);
task->set = 0;
exports_test_pong_return(task->read_result);
test_string_free(&task->read_result);
free(task);
return TEST_CALLBACK_CODE_EXIT;
}