Files
cosmopolite/clients/c/test.c

236 lines
6.3 KiB
C
Raw Normal View History

2015-06-14 21:41:43 +00:00
#include <assert.h>
2015-06-02 22:21:28 -07:00
#include <unistd.h>
2015-06-06 10:44:46 -07:00
#include "cosmopolite.h"
#include "cosmopolite-int.h"
2015-06-06 10:44:46 -07:00
2015-06-14 21:28:01 +00:00
#define RUN_TEST(func) run_test(#func, func)
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_GREEN "\x1b[32m"
#define ANSI_COLOR_YELLOW "\x1b[33m"
#define ANSI_COLOR_RESET "\x1b[0m"
2015-06-15 03:26:41 +00:00
typedef struct {
pthread_mutex_t lock;
pthread_cond_t cond;
const json_t *last_message;
bool logout_fired;
2015-06-18 04:27:17 +00:00
bool connect_fired;
2015-06-18 05:43:05 +00:00
bool disconnect_fired;
2015-06-15 03:26:41 +00:00
} test_state;
2015-06-18 04:27:17 +00:00
void on_connect(void *passthrough) {
test_state *state = passthrough;
assert(!pthread_mutex_lock(&state->lock));
state->connect_fired = true;
assert(!pthread_cond_signal(&state->cond));
assert(!pthread_mutex_unlock(&state->lock));
}
2015-06-18 05:43:05 +00:00
void on_disconnect(void *passthrough) {
test_state *state = passthrough;
assert(!pthread_mutex_lock(&state->lock));
state->disconnect_fired = true;
assert(!pthread_cond_signal(&state->cond));
assert(!pthread_mutex_unlock(&state->lock));
}
2015-06-15 03:26:41 +00:00
void on_logout(void *passthrough) {
test_state *state = passthrough;
assert(!pthread_mutex_lock(&state->lock));
state->logout_fired = true;
assert(!pthread_cond_signal(&state->cond));
assert(!pthread_mutex_unlock(&state->lock));
}
2015-06-14 21:41:43 +00:00
void on_message(const json_t *message, void *passthrough) {
2015-06-15 03:26:41 +00:00
test_state *state = passthrough;
assert(!pthread_mutex_lock(&state->lock));
state->last_message = message;
assert(!pthread_cond_signal(&state->cond));
assert(!pthread_mutex_unlock(&state->lock));
}
const json_t *wait_for_message(test_state *state) {
assert(!pthread_mutex_lock(&state->lock));
while (!state->last_message) {
assert(!pthread_cond_wait(&state->cond, &state->lock));
}
const json_t *ret = state->last_message;
state->last_message = NULL;
assert(!pthread_mutex_unlock(&state->lock));
return ret;
2015-06-14 21:41:43 +00:00
}
2015-06-15 03:26:41 +00:00
void wait_for_logout(test_state *state) {
assert(!pthread_mutex_lock(&state->lock));
while (!state->logout_fired) {
assert(!pthread_cond_wait(&state->cond, &state->lock));
2015-06-14 21:41:43 +00:00
}
2015-06-15 03:26:41 +00:00
state->logout_fired = false;
assert(!pthread_mutex_unlock(&state->lock));
}
2015-06-18 04:27:17 +00:00
void wait_for_connect(test_state *state) {
assert(!pthread_mutex_lock(&state->lock));
while (!state->connect_fired) {
assert(!pthread_cond_wait(&state->cond, &state->lock));
}
state->connect_fired = false;
assert(!pthread_mutex_unlock(&state->lock));
}
2015-06-18 05:43:05 +00:00
void wait_for_disconnect(test_state *state) {
assert(!pthread_mutex_lock(&state->lock));
while (!state->disconnect_fired) {
assert(!pthread_cond_wait(&state->cond, &state->lock));
}
state->disconnect_fired = false;
assert(!pthread_mutex_unlock(&state->lock));
}
2015-06-15 03:26:41 +00:00
test_state *create_test_state() {
test_state *ret = malloc(sizeof(test_state));
assert(ret);
assert(!pthread_mutex_init(&ret->lock, NULL));
assert(!pthread_cond_init(&ret->cond, NULL));
ret->last_message = NULL;
ret->logout_fired = false;
2015-06-18 04:27:17 +00:00
ret->connect_fired = false;
2015-06-18 05:43:05 +00:00
ret->disconnect_fired = false;
2015-06-14 21:41:43 +00:00
return ret;
2015-06-07 15:30:08 -07:00
}
2015-06-15 03:26:41 +00:00
void destroy_test_state(test_state *state) {
assert(!pthread_mutex_destroy(&state->lock));
assert(!pthread_cond_destroy(&state->cond));
free(state);
}
cosmo *create_client(test_state *state) {
2015-06-03 22:45:07 -07:00
char client_id[COSMO_UUID_SIZE];
cosmo_uuid(client_id);
2015-06-07 15:30:08 -07:00
cosmo_callbacks callbacks = {
2015-06-18 04:27:17 +00:00
.connect = on_connect,
2015-06-18 05:43:05 +00:00
.disconnect = on_disconnect,
2015-06-15 03:26:41 +00:00
.logout = on_logout,
.message = on_message,
2015-06-07 15:30:08 -07:00
};
2015-06-15 03:26:41 +00:00
return cosmo_create("https://playground.cosmopolite.org/cosmopolite", client_id, &callbacks, state);
2015-06-14 21:28:01 +00:00
}
json_t *random_subject(const char *readable_only_by, const char *writeable_only_by) {
char uuid[COSMO_UUID_SIZE];
cosmo_uuid(uuid);
char name[COSMO_UUID_SIZE + 20];
sprintf(name, "/test/%s", uuid);
return cosmo_subject(name, readable_only_by, writeable_only_by);
}
2015-06-14 21:41:43 +00:00
json_t *random_message() {
char uuid[COSMO_UUID_SIZE];
cosmo_uuid(uuid);
return json_string(uuid);
}
2015-06-15 03:26:41 +00:00
void run_test(const char *func_name, bool (*test)(test_state *)) {
test_state *state = create_test_state();
2015-06-14 21:28:01 +00:00
fprintf(stderr, ANSI_COLOR_YELLOW "%50s" ANSI_COLOR_RESET ": ", func_name);
2015-06-15 03:26:41 +00:00
if (test(state)) {
2015-06-14 21:28:01 +00:00
fprintf(stderr, ANSI_COLOR_GREEN "PASS" ANSI_COLOR_RESET "\n");
} else {
fprintf(stderr, ANSI_COLOR_RED "FAIL" ANSI_COLOR_RESET "\n");
}
2015-06-15 03:26:41 +00:00
destroy_test_state(state);
2015-06-14 21:28:01 +00:00
}
bool test_create_shutdown(test_state *state) {
2015-06-15 03:26:41 +00:00
cosmo *client = create_client(state);
2015-06-14 21:28:01 +00:00
cosmo_shutdown(client);
return true;
}
2015-06-15 03:26:41 +00:00
bool test_message_round_trip(test_state *state) {
cosmo *client = create_client(state);
2015-06-14 21:28:01 +00:00
json_t *subject = random_subject(NULL, NULL);
cosmo_subscribe(client, subject, -1, 0);
2015-06-14 21:41:43 +00:00
json_t *message_out = random_message();
cosmo_send_message(client, subject, message_out);
2015-06-15 03:26:41 +00:00
const json_t *message_in = wait_for_message(state);
2015-06-14 21:41:43 +00:00
assert(json_equal(message_out, json_object_get(message_in, "message")));
2015-06-03 22:24:07 -07:00
json_decref(subject);
2015-06-14 21:41:43 +00:00
json_decref(message_out);
2015-06-15 02:27:03 +00:00
2015-06-14 21:28:01 +00:00
cosmo_shutdown(client);
return true;
}
2015-06-02 22:21:28 -07:00
bool test_connect_logout_fires(test_state *state) {
2015-06-18 04:27:17 +00:00
cosmo *client = create_client(state);
wait_for_connect(state);
wait_for_logout(state);
2015-06-18 04:27:17 +00:00
cosmo_shutdown(client);
return true;
}
bool test_reconnect(test_state *state) {
2015-06-18 05:43:05 +00:00
cosmo *client = create_client(state);
wait_for_connect(state);
assert(!curl_easy_setopt(client->curl, CURLOPT_TIMEOUT_MS, 1));
wait_for_disconnect(state);
assert(!curl_easy_setopt(client->curl, CURLOPT_TIMEOUT_MS, 10000));
wait_for_connect(state);
cosmo_shutdown(client);
return true;
}
bool test_resubscribe(test_state *state) {
cosmo *client = create_client(state);
json_t *subject = random_subject(NULL, NULL);
cosmo_subscribe(client, subject, -1, 0);
json_t *message_out = random_message();
cosmo_send_message(client, subject, message_out);
const json_t *message_in = wait_for_message(state);
assert(json_equal(message_out, json_object_get(message_in, "message")));
json_decref(message_out);
// Reach in and reset the instance ID so we look new.
cosmo_uuid(client->instance_id);
message_out = random_message();
cosmo_send_message(client, subject, message_out);
message_in = wait_for_message(state);
assert(json_equal(message_out, json_object_get(message_in, "message")));
json_decref(message_out);
json_decref(subject);
cosmo_shutdown(client);
return true;
}
2015-06-15 03:26:41 +00:00
int main(int argc, char *argv[]) {
RUN_TEST(test_create_shutdown);
RUN_TEST(test_connect_logout_fires);
2015-06-18 04:27:17 +00:00
RUN_TEST(test_message_round_trip);
RUN_TEST(test_resubscribe);
RUN_TEST(test_reconnect);
2015-06-14 21:41:43 +00:00
2015-06-02 22:21:28 -07:00
return 0;
}