@@ -224,17 +224,31 @@ int test_init (const char *db_path, int init) {
224224 rc = db_exec (db , "SELECT cloudsync_init('activities');" ); RCHECK
225225 rc = db_exec (db , "SELECT cloudsync_init('workouts');" ); RCHECK
226226
227- // init network with JSON connection string
227+ // init network
228228 char network_init [1024 ];
229229 const char * test_db_id = getenv ("INTEGRATION_TEST_DATABASE_ID" );
230230 if (!test_db_id ) {
231231 fprintf (stderr , "Error: INTEGRATION_TEST_DATABASE_ID not set.\n" );
232232 exit (1 );
233233 }
234- snprintf (network_init , sizeof (network_init ),
235- "SELECT cloudsync_network_init('%s');" , test_db_id );
234+ const char * custom_address = getenv ("INTEGRATION_TEST_CLOUDSYNC_ADDRESS" );
235+ if (custom_address ) {
236+ snprintf (network_init , sizeof (network_init ),
237+ "SELECT cloudsync_network_init_custom('%s', '%s');" , custom_address , test_db_id );
238+ } else {
239+ snprintf (network_init , sizeof (network_init ),
240+ "SELECT cloudsync_network_init('%s');" , test_db_id );
241+ }
236242 rc = db_exec (db , network_init ); RCHECK
237243
244+ const char * apikey = getenv ("INTEGRATION_TEST_APIKEY" );
245+ if (apikey ) {
246+ char set_apikey [512 ];
247+ snprintf (set_apikey , sizeof (set_apikey ),
248+ "SELECT cloudsync_network_set_apikey('%s');" , apikey );
249+ rc = db_exec (db , set_apikey ); RCHECK
250+ }
251+
238252 rc = db_expect_int (db , "SELECT COUNT(*) as count FROM activities;" , 0 ); RCHECK
239253 rc = db_expect_int (db , "SELECT COUNT(*) as count FROM workouts;" , 0 ); RCHECK
240254 char value [UUID_STR_MAXLEN ];
@@ -294,17 +308,31 @@ int test_enable_disable(const char *db_path) {
294308 snprintf (sql , sizeof (sql ), "INSERT INTO users (id, name) VALUES ('%s-should-sync', '%s-should-sync');" , value , value );
295309 rc = db_exec (db , sql ); RCHECK
296310
297- // init network with JSON connection string
311+ // init network
298312 char network_init [1024 ];
299313 const char * test_db_id = getenv ("INTEGRATION_TEST_DATABASE_ID" );
300314 if (!test_db_id ) {
301315 fprintf (stderr , "Error: INTEGRATION_TEST_DATABASE_ID not set.\n" );
302316 exit (1 );
303317 }
304- snprintf (network_init , sizeof (network_init ),
305- "SELECT cloudsync_network_init('%s');" , test_db_id );
318+ const char * custom_address = getenv ("INTEGRATION_TEST_CLOUDSYNC_ADDRESS" );
319+ if (custom_address ) {
320+ snprintf (network_init , sizeof (network_init ),
321+ "SELECT cloudsync_network_init_custom('%s', '%s');" , custom_address , test_db_id );
322+ } else {
323+ snprintf (network_init , sizeof (network_init ),
324+ "SELECT cloudsync_network_init('%s');" , test_db_id );
325+ }
306326 rc = db_exec (db , network_init ); RCHECK
307327
328+ const char * apikey = getenv ("INTEGRATION_TEST_APIKEY" );
329+ if (apikey ) {
330+ char set_apikey [512 ];
331+ snprintf (set_apikey , sizeof (set_apikey ),
332+ "SELECT cloudsync_network_set_apikey('%s');" , apikey );
333+ rc = db_exec (db , set_apikey ); RCHECK
334+ }
335+
308336 rc = db_exec (db , "SELECT cloudsync_network_send_changes();" ); RCHECK
309337 rc = db_exec (db , "SELECT cloudsync_cleanup('users');" ); RCHECK
310338 rc = db_exec (db , "SELECT cloudsync_cleanup('activities');" ); RCHECK
@@ -324,6 +352,13 @@ int test_enable_disable(const char *db_path) {
324352 // init network with connection string + apikey
325353 rc = db_exec (db2 , network_init ); RCHECK
326354
355+ if (apikey ) {
356+ char set_apikey2 [512 ];
357+ snprintf (set_apikey2 , sizeof (set_apikey2 ),
358+ "SELECT cloudsync_network_set_apikey('%s');" , apikey );
359+ rc = db_exec (db2 , set_apikey2 ); RCHECK
360+ }
361+
327362 rc = db_expect_gt0 (db2 , "SELECT cloudsync_network_sync(250,10) ->> '$.receive.rows';" ); RCHECK
328363
329364 snprintf (sql , sizeof (sql ), "SELECT COUNT (* ) FROM users WHERE name = '%s' ;", value);
@@ -362,10 +397,26 @@ int test_offline_error(const char *db_path) {
362397 }
363398
364399 char network_init [512 ];
365- snprintf (network_init , sizeof (network_init ), "SELECT cloudsync_network_init('%s');" , offline_db_id );
400+ const char * custom_address = getenv ("INTEGRATION_TEST_CLOUDSYNC_ADDRESS" );
401+ if (custom_address ) {
402+ snprintf (network_init , sizeof (network_init ),
403+ "SELECT cloudsync_network_init_custom('%s', '%s');" , custom_address , offline_db_id );
404+ } else {
405+ snprintf (network_init , sizeof (network_init ),
406+ "SELECT cloudsync_network_init('%s');" , offline_db_id );
407+ }
366408 rc = db_exec (db , network_init );
367409 RCHECK
368410
411+ const char * apikey = getenv ("INTEGRATION_TEST_APIKEY" );
412+ if (apikey ) {
413+ char set_apikey [512 ];
414+ snprintf (set_apikey , sizeof (set_apikey ),
415+ "SELECT cloudsync_network_set_apikey('%s');" , apikey );
416+ rc = db_exec (db , set_apikey );
417+ RCHECK
418+ }
419+
369420 // Try to sync - this should fail with the expected error
370421 char * errmsg = NULL ;
371422 rc = sqlite3_exec (db , "SELECT cloudsync_network_sync();" , NULL , NULL , & errmsg );
@@ -376,17 +427,35 @@ int test_offline_error(const char *db_path) {
376427 goto abort_test ;
377428 }
378429
379- // Verify the error message contains the expected text
380- const char * expected_error = "cloudsync_network_send_changes unable to upload BLOB changes to remote host" ;
381- if (!errmsg || strstr (errmsg , expected_error ) == NULL ) {
382- printf ("Error: Expected error message containing '%s', but got '%s'\n" ,
383- expected_error , errmsg ? errmsg : "NULL" );
384- if (errmsg ) sqlite3_free (errmsg );
430+ // Verify the error JSON contains expected fields using SQLite JSON extraction
431+ if (!errmsg ) {
432+ printf ("Error: Expected an error message, but got NULL\n" );
385433 rc = SQLITE_ERROR ;
386434 goto abort_test ;
387435 }
388436
389- if (errmsg ) sqlite3_free (errmsg );
437+ char verify_sql [1024 ];
438+ snprintf (verify_sql , sizeof (verify_sql ),
439+ "SELECT json_extract('%s', '$.errors[0].status');" , errmsg );
440+ rc = db_expect_str (db , verify_sql , "500" );
441+ if (rc != SQLITE_OK ) { printf ("Offline error: unexpected status in: %s\n" , errmsg ); sqlite3_free (errmsg ); goto abort_test ; }
442+
443+ snprintf (verify_sql , sizeof (verify_sql ),
444+ "SELECT json_extract('%s', '$.errors[0].code');" , errmsg );
445+ rc = db_expect_str (db , verify_sql , "internal_server_error" );
446+ if (rc != SQLITE_OK ) { printf ("Offline error: unexpected code in: %s\n" , errmsg ); sqlite3_free (errmsg ); goto abort_test ; }
447+
448+ snprintf (verify_sql , sizeof (verify_sql ),
449+ "SELECT json_extract('%s', '$.errors[0].title');" , errmsg );
450+ rc = db_expect_str (db , verify_sql , "Internal Server Error" );
451+ if (rc != SQLITE_OK ) { printf ("Offline error: unexpected title in: %s\n" , errmsg ); sqlite3_free (errmsg ); goto abort_test ; }
452+
453+ snprintf (verify_sql , sizeof (verify_sql ),
454+ "SELECT json_extract('%s', '$.errors[0].detail');" , errmsg );
455+ rc = db_expect_str (db , verify_sql , "failed to resolve token data: failed to resolve db user for api key: db: connect sqlitecloud failed after 3 attempts: Your free node has been paused due to inactivity. To resume usage, please restart your node from your dashboard: https://dashboard.sqlitecloud.io" );
456+ if (rc != SQLITE_OK ) { printf ("Offline error: unexpected detail in: %s\n" , errmsg ); sqlite3_free (errmsg ); goto abort_test ; }
457+
458+ sqlite3_free (errmsg );
390459 rc = SQLITE_OK ;
391460
392461ABORT_TEST
@@ -588,4 +657,4 @@ int main (void) {
588657
589658 printf ("\n" );
590659 return rc ;
591- }
660+ }
0 commit comments