From eecdbf68529225658ac860bdb3e1c75ff06e9633 Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Thu, 27 Nov 2025 16:06:33 -0500 Subject: [PATCH] ssb: Exercise at least calling adding/removing blocks in a test. --- core/core.js | 14 +++-------- src/ssb.db.c | 16 +++++++++++- src/ssb.tests.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ src/ssb.tests.h | 6 +++++ src/tests.c | 3 ++- 5 files changed, 93 insertions(+), 12 deletions(-) diff --git a/core/core.js b/core/core.js index fdde1e7c..da7e348c 100644 --- a/core/core.js +++ b/core/core.js @@ -508,19 +508,13 @@ async function getProcessBlob(blobId, key, options) { } }; imports.ssb.addBlock = async function (id) { - await imports.core.permissionTest( - 'modify_blocks', - `Block ${id}.` - ); + await imports.core.permissionTest('modify_blocks', `Block ${id}.`); await ssb_internal.addBlock(id); - } + }; imports.ssb.removeBlock = async function (id) { - await imports.core.permissionTest( - 'modify_blocks', - `Unblock ${id}.` - ); + await imports.core.permissionTest('modify_blocks', `Unblock ${id}.`); await ssb_internal.removeBlock(id); - } + }; } if ( diff --git a/src/ssb.db.c b/src/ssb.db.c index c8bb917b..0d1de3f9 100644 --- a/src/ssb.db.c +++ b/src/ssb.db.c @@ -2876,7 +2876,7 @@ tf_ssb_identity_info_t* tf_ssb_db_get_identity_info(tf_ssb_t* ssb, const char* u void tf_ssb_db_add_block(sqlite3* db, const char* id) { sqlite3_stmt* statement = NULL; - if (sqlite3_prepare_v2(db, "INSERT INTO blocks (id, timestamp) VALUES (?, ?) ON CONFLICT DO NOTHING", -1, &statement, NULL) == SQLITE_OK) + if (sqlite3_prepare_v2(db, "INSERT INTO blocks (id, timestamp) VALUES (?, unixepoch() * 1000) ON CONFLICT DO NOTHING", -1, &statement, NULL) == SQLITE_OK) { if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK) { @@ -2887,6 +2887,20 @@ void tf_ssb_db_add_block(sqlite3* db, const char* id) } sqlite3_finalize(statement); } + if (sqlite3_prepare_v2(db, + "INSERT INTO blocks (id, timestamp) SELECT messages_refs.ref AS id, unixepoch() * 1000 AS timestamp FROM messages_refs WHERE messages_refs.message = ? ON CONFLICT DO " + "NOTHING", + -1, &statement, NULL) == SQLITE_OK) + { + if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK) + { + if (sqlite3_step(statement) != SQLITE_DONE) + { + tf_printf("add block messages ref: %s\n", sqlite3_errmsg(db)); + } + } + sqlite3_finalize(statement); + } } void tf_ssb_db_remove_block(sqlite3* db, const char* id) diff --git a/src/ssb.tests.c b/src/ssb.tests.c index 1421488d..6c23b393 100644 --- a/src/ssb.tests.c +++ b/src/ssb.tests.c @@ -1851,4 +1851,70 @@ void tf_ssb_test_following_perf(const tf_test_options_t* options) uv_run(&loop, UV_RUN_DEFAULT); uv_loop_close(&loop); } + +static void _store_callback(const char* id, bool verified, bool is_new, void* user_data) +{ + tf_string_set(user_data, k_id_base64_len, id); +} + +void tf_ssb_test_blocks(const tf_test_options_t* options) +{ + uv_loop_t loop = { 0 }; + uv_loop_init(&loop); + + tf_printf("Testing blocks.\n"); + unlink("out/test_db0.sqlite"); + tf_ssb_t* ssb = tf_ssb_create(&loop, NULL, "file:out/test_db0.sqlite", NULL); + + tf_ssb_generate_keys(ssb); + + uint8_t priv[512] = { 0 }; + tf_ssb_get_private_key(ssb, priv, sizeof(priv)); + + char id[k_id_base64_len] = { 0 }; + tf_ssb_whoami(ssb, id, sizeof(id)); + tf_printf("ID %s\n", id); + + char blob_id[k_id_base64_len] = { 0 }; + const char* k_blob = "Hello, blob!"; + bool blob_stored = false; + tf_ssb_add_blob_stored_callback(ssb, _blob_stored, NULL, &blob_stored); + tf_ssb_db_blob_store(ssb, (const uint8_t*)k_blob, strlen(k_blob), blob_id, sizeof(blob_id), NULL); + tf_ssb_notify_blob_stored(ssb, blob_id); + tf_ssb_remove_blob_stored_callback(ssb, _blob_stored, &blob_stored); + assert(blob_stored); + + JSContext* context = tf_ssb_get_context(ssb); + JSValue obj = JS_NewObject(context); + JS_SetPropertyStr(context, obj, "type", JS_NewString(context, "post")); + JS_SetPropertyStr(context, obj, "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, obj, "mentions", mentions); + JSValue signed_message = tf_ssb_sign_message(ssb, id, priv, obj, NULL, 0); + char message_id[k_id_base64_len] = { 0 }; + tf_ssb_verify_strip_and_store_message(ssb, signed_message, _store_callback, message_id); + JS_FreeValue(context, signed_message); + while (!*message_id) + { + uv_run(tf_ssb_get_loop(ssb), UV_RUN_ONCE); + } + JS_FreeValue(context, obj); + + sqlite3* db = tf_ssb_acquire_db_writer(ssb); + tf_ssb_db_add_block(db, message_id); + tf_ssb_db_add_block(db, blob_id); + tf_ssb_db_add_block(db, id); + tf_ssb_db_remove_block(db, blob_id); + tf_ssb_db_remove_block(db, message_id); + tf_ssb_db_remove_block(db, id); + tf_ssb_release_db_writer(ssb, db); + + tf_ssb_destroy(ssb); + + uv_run(&loop, UV_RUN_DEFAULT); + uv_loop_close(&loop); +} #endif diff --git a/src/ssb.tests.h b/src/ssb.tests.h index c9ed3733..4aa3e17a 100644 --- a/src/ssb.tests.h +++ b/src/ssb.tests.h @@ -107,4 +107,10 @@ void tf_ssb_test_cli(const tf_test_options_t* options); */ void tf_ssb_test_following_perf(const tf_test_options_t* options); +/** +** Test blocks. +** @param options The test options. +*/ +void tf_ssb_test_blocks(const tf_test_options_t* options); + /** @} */ diff --git a/src/tests.c b/src/tests.c index 18b7a048..49ceb7f7 100644 --- a/src/tests.c +++ b/src/tests.c @@ -982,7 +982,6 @@ void tf_tests(const tf_test_options_t* options) _tf_test_run(options, "b64", _test_b64, false); _tf_test_run(options, "rooms", tf_ssb_test_rooms, false); _tf_test_run(options, "bench", tf_ssb_test_bench, false); - _tf_test_run(options, "auto", _test_auto, false); _tf_test_run(options, "go-ssb-room", tf_ssb_test_go_ssb_room, true); _tf_test_run(options, "encrypt", tf_ssb_test_encrypt, false); _tf_test_run(options, "peer_exchange", tf_ssb_test_peer_exchange, false); @@ -994,6 +993,8 @@ void tf_tests(const tf_test_options_t* options) _tf_test_run(options, "triggers", tf_ssb_test_triggers, false); _tf_test_run(options, "cli", tf_ssb_test_cli, false); _tf_test_run(options, "following_perf", tf_ssb_test_following_perf, true); + _tf_test_run(options, "blocks", tf_ssb_test_blocks, true); + _tf_test_run(options, "auto", _test_auto, false); tf_printf("Tests completed.\n"); #endif }