tildefriends/src/ssb.tests.c

245 lines
6.3 KiB
C
Raw Normal View History

#include "ssb.h"
#include "ssb.db.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>
#include <uv.h>
static void _tf_ssb_test_id_conversion()
{
printf("Testing id conversion.\n");
uint8_t bin[k_id_bin_len] = { 0 };
char str[k_id_base64_len] = { 0 };
const char* k_id = "@bzRTe6hgOII2yZ1keGGoNoQgostjQc830trHc453crY=.ed25519";
(void)bin;
(void)str;
(void)k_id;
assert(tf_ssb_id_str_to_bin(bin, k_id));
assert(tf_ssb_id_bin_to_str(str, sizeof(str), bin));
assert(strcmp(str, k_id) == 0);
}
typedef struct _test_t {
tf_ssb_t* ssb0;
tf_ssb_t* ssb1;
int connection_count0;
int connection_count1;
} test_t;
static void _ssb_test_connections_changed(tf_ssb_t* ssb, tf_ssb_change_t change, tf_ssb_connection_t* connection, void* user_data)
{
test_t* test = user_data;
int count = 0;
const char** c = tf_ssb_get_connection_ids(ssb);
for (const char** p = c; *p; p++) {
count++;
}
free(c);
if (ssb == test->ssb0) {
printf("callback0 change=%d connection=%p\n", change, connection);
test->connection_count0 = count;
} else if (ssb == test->ssb1) {
printf("callback1 change=%d connection=%p\n", change, connection);
test->connection_count1 = count;
}
printf("conns = %d %d\n", test->connection_count0, test->connection_count1);
}
static void _count_messages_callback(JSValue row, void* user_data)
{
int* count = user_data;
++*count;
}
static int _ssb_test_count_messages(tf_ssb_t* ssb)
{
int count = 0;
tf_ssb_db_visit_query(ssb, "SELECT * FROM messages", JS_UNDEFINED, _count_messages_callback, &count);
return count;
}
static void _tf_ssb_test_ssb()
{
printf("Testing SSB.\n");
sqlite3* db0 = NULL;
sqlite3* db1 = NULL;
assert(sqlite3_open(":memory:", &db0) == SQLITE_OK);
assert(sqlite3_open(":memory:", &db1) == SQLITE_OK);
uv_loop_t loop = { 0 };
uv_loop_init(&loop);
tf_ssb_t* ssb0 = tf_ssb_create(&loop, NULL, db0, NULL);
tf_ssb_t* ssb1 = tf_ssb_create(&loop, NULL, db1, NULL);
test_t test = {
.ssb0 = ssb0,
.ssb1 = ssb1,
};
tf_ssb_add_connections_changed_callback(ssb0, _ssb_test_connections_changed, &test);
tf_ssb_add_connections_changed_callback(ssb1, _ssb_test_connections_changed, &test);
tf_ssb_generate_keys(ssb0);
tf_ssb_generate_keys(ssb1);
char id0[k_id_base64_len] = { 0 };
char id1[k_id_base64_len] = { 0 };
bool b = tf_ssb_whoami(ssb0, id0, sizeof(id0));
(void)b;
assert(b);
b = tf_ssb_whoami(ssb0, id0, sizeof(id0));
assert(b);
printf("ID %s and %s\n", id0, id1);
char blob_id[k_id_base64_len] = { 0 };
const char* k_blob = "Hello, blob!";
b = tf_ssb_db_blob_store(ssb0, (const uint8_t*)k_blob, strlen(k_blob), blob_id, sizeof(blob_id));
assert(b);
tf_ssb_append_post(ssb0, "Hello, world!");
tf_ssb_append_post(ssb0, "First post.");
JSContext* context = tf_ssb_get_context(ssb0);
JSValue message = JS_NewObject(context);
JS_SetPropertyStr(context, message, "type", JS_NewString(context, "post"));
JS_SetPropertyStr(context, message, "text", JS_NewString(context, "First post."));
JSValue mentions = JS_NewArray(context);
JSValue mention = JS_NewObject(context);
JS_SetPropertyStr(context, mention, "link", JS_NewString(context, blob_id));
JS_SetPropertyUint32(context, mentions, 0, mention);
JS_SetPropertyStr(context, message, "mentions", mentions);
tf_ssb_append_message(ssb0, message);
JS_FreeValue(context, message);
assert(tf_ssb_db_blob_get(ssb0, blob_id, NULL, NULL));
assert(!tf_ssb_db_blob_get(ssb1, blob_id, NULL, NULL));
tf_ssb_server_open(ssb0, 12347);
uint8_t id0bin[k_id_bin_len];
tf_ssb_id_str_to_bin(id0bin, id0);
tf_ssb_connect(ssb1, "127.0.0.1", 12347, id0bin);
while (test.connection_count0 != 1 ||
test.connection_count1 != 1) {
uv_run(&loop, UV_RUN_ONCE);
}
tf_ssb_server_close(ssb0);
while (_ssb_test_count_messages(ssb1) < 3) {
uv_run(&loop, UV_RUN_ONCE);
}
printf("waiting for blob\n");
while (!tf_ssb_db_blob_get(ssb1, blob_id, NULL, NULL)) {
uv_run(&loop, UV_RUN_ONCE);
}
printf("done\n");
tf_ssb_send_close(ssb1);
uv_run(&loop, UV_RUN_DEFAULT);
tf_ssb_destroy(ssb0);
tf_ssb_destroy(ssb1);
uv_loop_close(&loop);
sqlite3_close(db0);
sqlite3_close(db1);
}
static void _tf_ssb_test_following()
{
printf("Testing following.\n");
sqlite3* db0 = NULL;
assert(sqlite3_open(":memory:", &db0) == SQLITE_OK);
uv_loop_t loop = { 0 };
uv_loop_init(&loop);
tf_ssb_t* ssb0 = tf_ssb_create(&loop, NULL, db0, NULL);
tf_ssb_generate_keys(ssb0);
tf_ssb_t* ssb1 = tf_ssb_create(&loop, NULL, db0, NULL);
tf_ssb_generate_keys(ssb1);
tf_ssb_t* ssb2 = tf_ssb_create(&loop, NULL, db0, NULL);
tf_ssb_generate_keys(ssb2);
char id0[k_id_base64_len] = { 0 };
char id1[k_id_base64_len] = { 0 };
char id2[k_id_base64_len] = { 0 };
tf_ssb_whoami(ssb0, id0, sizeof(id0));
tf_ssb_whoami(ssb1, id1, sizeof(id1));
tf_ssb_whoami(ssb2, id2, sizeof(id2));
JSContext* context = NULL;
JSValue message;
#define FOLLOW(ssb, id, follow) \
context = tf_ssb_get_context(ssb); \
message = JS_NewObject(context); \
JS_SetPropertyStr(context, message, "type", JS_NewString(context, "contact")); \
JS_SetPropertyStr(context, message, "contact", JS_NewString(context, id)); \
JS_SetPropertyStr(context, message, "following", follow ? JS_TRUE : JS_FALSE); \
tf_ssb_append_message(ssb, message); \
JS_FreeValue(context, message); \
context = NULL
#define DUMP(id, depth) \
do { \
printf("following %d:\n", depth); \
const char** tf_ssb_get_following_deep(tf_ssb_t* ssb_param, const char** ids, int depth_param); \
const char** f = tf_ssb_get_following_deep(ssb0, (const char*[]) { id, NULL }, depth); \
for (const char** p = f; p && *p; p++) { \
printf("* %s\n", *p); \
} \
printf("\n"); \
free(f); \
} while (0)
FOLLOW(ssb0, id1, true);
FOLLOW(ssb1, id2, true);
FOLLOW(ssb2, id0, true);
DUMP(id0, 2);
DUMP(id1, 2);
DUMP(id2, 2);
FOLLOW(ssb0, id1, false);
//FOLLOW(ssb0, id1, true);
//FOLLOW(ssb0, id1, true);
DUMP(id0, 1);
DUMP(id1, 2);
//FOLLOW(ssb0, id1, false);
//DUMP(1);
//DUMP(1);
#undef FOLLOW
#undef DUMP
uv_run(&loop, UV_RUN_DEFAULT);
tf_ssb_destroy(ssb0);
tf_ssb_destroy(ssb1);
tf_ssb_destroy(ssb2);
uv_loop_close(&loop);
sqlite3_close(db0);
}
void tf_ssb_test()
{
printf("tf_ssb_test() starting.\n");
_tf_ssb_test_id_conversion();
_tf_ssb_test_ssb();
_tf_ssb_test_following();
printf("tf_ssb_test() completed successfully.\n");
}