@@ -313,6 +313,91 @@ int test_enable_disable(const char *db_path) {
313313ABORT_TEST
314314}
315315
316+ int test_offline_error (const char * db_path ) {
317+ sqlite3 * db = NULL ;
318+ int rc = open_load_ext (db_path , & db );
319+ RCHECK
320+
321+ rc = db_exec (db , "CREATE TABLE IF NOT EXISTS test_table (id TEXT PRIMARY KEY NOT NULL, value TEXT NOT NULL DEFAULT '', created_at TEXT DEFAULT CURRENT_TIMESTAMP);" );
322+ RCHECK
323+
324+ rc = db_exec (db , "SELECT cloudsync_init('test_table');" );
325+ RCHECK
326+
327+ rc = db_exec (db , "INSERT INTO test_table (id, value) VALUES (cloudsync_uuid(), 'test1'), (cloudsync_uuid(), 'test2');" );
328+ RCHECK
329+
330+ // Initialize network with offline connection string
331+ const char * offline_conn_str = getenv ("CONNECTION_STRING_OFFLINE_PROJECT" );
332+ if (!offline_conn_str ) {
333+ printf ("Skipping offline error test: CONNECTION_STRING_OFFLINE_PROJECT not set.\n" );
334+ rc = SQLITE_OK ;
335+ goto abort_test ;
336+ }
337+
338+ char network_init [512 ];
339+ snprintf (network_init , sizeof (network_init ), "SELECT cloudsync_network_init('%s');" , offline_conn_str );
340+ rc = db_exec (db , network_init );
341+ RCHECK
342+
343+ // Try to sync - this should fail with the expected error
344+ char * errmsg = NULL ;
345+ rc = sqlite3_exec (db , "SELECT cloudsync_network_sync();" , NULL , NULL , & errmsg );
346+
347+ if (rc == SQLITE_OK ) {
348+ printf ("Error: Expected network sync to fail, but it succeeded.\n" );
349+ rc = SQLITE_ERROR ;
350+ goto abort_test ;
351+ }
352+
353+ // Verify the error message contains the expected text
354+ const char * expected_error = "cloudsync_network_send_changes unable to upload BLOB changes to remote host" ;
355+ if (!errmsg || strstr (errmsg , expected_error ) == NULL ) {
356+ printf ("Error: Expected error message containing '%s', but got '%s'\n" ,
357+ expected_error , errmsg ? errmsg : "NULL" );
358+ if (errmsg ) sqlite3_free (errmsg );
359+ rc = SQLITE_ERROR ;
360+ goto abort_test ;
361+ }
362+
363+ if (errmsg ) sqlite3_free (errmsg );
364+ rc = SQLITE_OK ;
365+
366+ ABORT_TEST
367+ }
368+
369+ int test_double_empty_network_init (const char * db_path ) {
370+ sqlite3 * db = NULL ;
371+ int rc = open_load_ext (db_path , & db );
372+ RCHECK
373+
374+ // First call with empty string - should return error
375+ char * errmsg1 = NULL ;
376+ rc = sqlite3_exec (db , "SELECT cloudsync_network_init('');" , NULL , NULL , & errmsg1 );
377+ if (rc == SQLITE_OK ) {
378+ printf ("Error: First cloudsync_network_init('') should have failed but succeeded\n" );
379+ if (errmsg1 ) sqlite3_free (errmsg1 );
380+ rc = SQLITE_ERROR ;
381+ goto abort_test ;
382+ }
383+ if (errmsg1 ) sqlite3_free (errmsg1 );
384+
385+ // Second call with empty string - should also return error (not segfault)
386+ char * errmsg2 = NULL ;
387+ rc = sqlite3_exec (db , "SELECT cloudsync_network_init('');" , NULL , NULL , & errmsg2 );
388+ if (rc == SQLITE_OK ) {
389+ printf ("Error: Second cloudsync_network_init('') should have failed but succeeded\n" );
390+ if (errmsg2 ) sqlite3_free (errmsg2 );
391+ rc = SQLITE_ERROR ;
392+ goto abort_test ;
393+ }
394+ if (errmsg2 ) sqlite3_free (errmsg2 );
395+
396+ rc = SQLITE_OK ;
397+
398+ ABORT_TEST
399+ }
400+
316401int version (void ){
317402 sqlite3 * db = NULL ;
318403 int rc = open_load_ext (":memory:" , & db );
@@ -380,6 +465,8 @@ int main (void) {
380465 rc += test_report ("Is Enabled Test:" , test_is_enabled (DB_PATH ));
381466 rc += test_report ("DB Version Test:" , test_db_version (DB_PATH ));
382467 rc += test_report ("Enable Disable Test:" , test_enable_disable (DB_PATH ));
468+ rc += test_report ("Offline Error Test:" , test_offline_error (":memory:" ));
469+ rc += test_report ("Double Empty Init Test:" , test_double_empty_network_init (":memory:" ));
383470
384471 remove (DB_PATH ); // remove the database file
385472
0 commit comments