Skip to content

Commit ce2affd

Browse files
committed
Add multi-cycle delete/resurrect regression test
1 parent 406f4be commit ce2affd

1 file changed

Lines changed: 76 additions & 0 deletions

File tree

test/unit.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12485,6 +12485,81 @@ bool do_test_delete_resurrect_ordering (int nclients, bool print_result, bool cl
1248512485
return result;
1248612486
}
1248712487

12488+
bool do_test_delete_resurrect_multi_cycle (int nclients, bool print_result, bool cleanup_databases) {
12489+
sqlite3 *db[3] = {NULL, NULL, NULL};
12490+
bool result = false;
12491+
12492+
time_t timestamp = time(NULL);
12493+
int saved_counter = test_counter;
12494+
12495+
for (int i = 0; i < 3; i++) {
12496+
db[i] = do_create_database_file(i, timestamp, test_counter++);
12497+
if (!db[i]) return false;
12498+
12499+
int rc = sqlite3_exec(db[i], "CREATE TABLE test_tbl (id TEXT PRIMARY KEY, val TEXT);", NULL, NULL, NULL);
12500+
if (rc != SQLITE_OK) goto finalize;
12501+
rc = sqlite3_exec(db[i], "SELECT cloudsync_init('test_tbl');", NULL, NULL, NULL);
12502+
if (rc != SQLITE_OK) goto finalize;
12503+
}
12504+
12505+
// Initial insert and full sync
12506+
if (sqlite3_exec(db[0], "INSERT INTO test_tbl VALUES ('row1', 'original');", NULL, NULL, NULL) != SQLITE_OK) goto finalize;
12507+
if (!do_merge_using_payload(db[0], db[1], false, true)) goto finalize;
12508+
if (!do_merge_using_payload(db[0], db[2], false, true)) goto finalize;
12509+
12510+
// Cycle 1: A deletes, B resurrects, C receives resurrection before stale delete.
12511+
if (sqlite3_exec(db[0], "DELETE FROM test_tbl WHERE id = 'row1';", NULL, NULL, NULL) != SQLITE_OK) goto finalize;
12512+
if (!do_merge_using_payload(db[0], db[1], true, true)) goto finalize;
12513+
12514+
if (sqlite3_exec(db[1], "INSERT INTO test_tbl VALUES ('row1', 'resurrected_by_b');", NULL, NULL, NULL) != SQLITE_OK) goto finalize;
12515+
if (!do_merge_using_payload(db[1], db[2], true, true)) goto finalize;
12516+
if (!do_merge_using_payload(db[0], db[2], true, true)) goto finalize;
12517+
if (!do_merge_using_payload(db[1], db[0], true, true)) goto finalize;
12518+
12519+
// Cycle 2: B deletes, A resurrects, C again receives resurrection before stale delete.
12520+
if (sqlite3_exec(db[1], "DELETE FROM test_tbl WHERE id = 'row1';", NULL, NULL, NULL) != SQLITE_OK) goto finalize;
12521+
if (!do_merge_using_payload(db[1], db[0], true, true)) goto finalize;
12522+
12523+
if (sqlite3_exec(db[0], "INSERT INTO test_tbl VALUES ('row1', 'resurrected_by_a_again');", NULL, NULL, NULL) != SQLITE_OK) goto finalize;
12524+
if (!do_merge_using_payload(db[0], db[2], true, true)) goto finalize;
12525+
if (!do_merge_using_payload(db[1], db[2], true, true)) goto finalize;
12526+
if (!do_merge_using_payload(db[0], db[1], true, true)) goto finalize;
12527+
12528+
const char *query = "SELECT * FROM test_tbl ORDER BY id;";
12529+
result = do_compare_queries(db[0], query, db[1], query, -1, -1, print_result);
12530+
if (result) result = do_compare_queries(db[0], query, db[2], query, -1, -1, print_result);
12531+
12532+
if (result) {
12533+
for (int i = 0; i < 3; i++) {
12534+
int64_t count = do_select_int(db[i], "SELECT COUNT(*) FROM test_tbl WHERE id = 'row1';");
12535+
int64_t live_sentinel = do_select_int(db[i], "SELECT COUNT(*) FROM test_tbl_cloudsync WHERE col_name = '__[RIP]__' AND col_version % 2 = 1;");
12536+
12537+
if (count != 1) {
12538+
printf("delete_resurrect_multi_cycle: expected row1 to exist on db[%d], count=%" PRId64 "\n", i, count);
12539+
result = false;
12540+
break;
12541+
}
12542+
12543+
if (live_sentinel != 1) {
12544+
printf("delete_resurrect_multi_cycle: expected 1 live sentinel on db[%d], got=%" PRId64 "\n", i, live_sentinel);
12545+
result = false;
12546+
break;
12547+
}
12548+
}
12549+
}
12550+
12551+
finalize:
12552+
for (int i = 0; i < 3; i++) {
12553+
if (db[i]) close_db(db[i]);
12554+
if (cleanup_databases) {
12555+
char buf[256];
12556+
do_build_database_path(buf, i, timestamp, saved_counter++);
12557+
file_delete_internal(buf);
12558+
}
12559+
}
12560+
return result;
12561+
}
12562+
1248812563
bool do_test_large_composite_pk (int nclients, bool print_result, bool cleanup_databases) {
1248912564
sqlite3 *db[2] = {NULL, NULL};
1249012565
bool result = false;
@@ -12804,6 +12879,7 @@ int main (int argc, const char * argv[]) {
1280412879
result += test_report("Payload Idempotency Test:", do_test_payload_idempotency(2, print_result, cleanup_databases));
1280512880
result += test_report("CL Tiebreak Test:", do_test_causal_length_tiebreak(3, print_result, cleanup_databases));
1280612881
result += test_report("Delete/Resurrect Order:", do_test_delete_resurrect_ordering(3, print_result, cleanup_databases));
12882+
result += test_report("Delete/Resurrect Multi-Cycle:", do_test_delete_resurrect_multi_cycle(3, print_result, cleanup_databases));
1280712883
result += test_report("Large Composite PK Test:", do_test_large_composite_pk(2, print_result, cleanup_databases));
1280812884
result += test_report("Schema Hash Mismatch:", do_test_schema_hash_mismatch(2, print_result, cleanup_databases));
1280912885
result += test_report("Stale Table Settings:", do_test_stale_table_settings(cleanup_databases));

0 commit comments

Comments
 (0)