Files
2026-07-13 12:32:25 +08:00

120 lines
4.9 KiB
Bash

#!/usr/bin/env bats
load $BATS_TEST_DIRNAME/setup/common.bash
setup() {
setup_common
}
teardown() {
teardown_common
}
# This test exercises the push/pull/clone workflow across two independent Doltgres server
# processes, each with its own data directory, coordinating only through a shared
# file-system remote.
@test 'remotes-file-system: clone from a fresh server, then push/pull round-trip data, a sequence, an enum type, and a function' {
mkdir remote
REMOTE_URL="file://$(pwd)/remote"
# --- Server A: seed a table, a sequence, a custom enum type, and a user-defined function --
# (all serialized at the Doltgres layer, not the Dolt layer -- see core/rootobject) -- commit,
# and push to the file-system remote ---
mkdir serverA
cd serverA
start_sql_server
query_server <<SQL
CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');
CREATE FUNCTION double_it(x INT) RETURNS INT AS \$\$ BEGIN RETURN x * 2; END; \$\$ LANGUAGE plpgsql;
CREATE TABLE items (id INT PRIMARY KEY, label TEXT NOT NULL, feeling mood);
INSERT INTO items VALUES (1, 'apple', 'happy'), (2, 'banana', 'sad');
CREATE SEQUENCE counter START 100 INCREMENT 50;
SELECT nextval('counter'); -- advances to 100
SELECT dolt_commit('-Am', 'seed items, counter, mood type, and double_it function');
SELECT dolt_remote('add', 'origin', '$REMOTE_URL');
SELECT dolt_push('origin', 'main');
SQL
stop_sql_server
cd ..
# --- Server B: an entirely separate, freshly-started server with its own data directory;
# it shares no process, session, or in-memory state with server A. Clone from the remote. ---
mkdir serverB
cd serverB
start_sql_server
query_server -c "SELECT dolt_clone('$REMOTE_URL', 'cloned');"
# The enum type definition itself (not just data using it) must have transferred. Checked as
# separate substrings (rather than one "id | label | feeling" string) because psql's tuples-only
# output pads each column to its widest value ("apple" pads out to match "banana"'s width), so
# the exact spacing between columns isn't stable across rows.
run query_server_for_db cloned -t -c "SELECT id, label, feeling::text FROM items ORDER BY id;"
[ "$status" -eq 0 ]
[[ "$output" =~ "1 | apple" ]] || false
[[ "$output" =~ "happy" ]] || false
[[ "$output" =~ "2 | banana" ]] || false
[[ "$output" =~ "sad" ]] || false
# The user-defined function must also be callable post-clone.
run query_server_for_db cloned -c "SELECT double_it(21);"
[ "$status" -eq 0 ]
[[ "$output" =~ "42" ]] || false
# Must reflect server A's current value (100), not reset to the sequence's start value. Read
# via pg_sequences rather than calling nextval() here, since nextval() itself writes the
# sequence's current value and would leave the clone with an uncommitted change, which the
# pull below would then reject with "cannot merge with uncommitted changes".
run query_server_for_db cloned -c "SELECT last_value FROM pg_sequences WHERE sequencename = 'counter';"
[ "$status" -eq 0 ]
[[ "$output" =~ "100" ]] || false
stop_sql_server
cd ..
# --- Back on server A: advance the table (using the enum type again) and the sequence
# further, and push again ---
cd serverA
start_sql_server
query_server <<SQL
INSERT INTO items VALUES (3, 'cherry', 'ok');
SELECT nextval('counter'); -- advances to 150
SELECT dolt_commit('-Am', 'add cherry and advance counter');
SELECT dolt_push('origin', 'main');
SQL
stop_sql_server
cd ..
# --- Back on server B (also restarted fresh): pull the update into the clone ---
cd serverB
start_sql_server
run query_server_for_db cloned -c "SELECT dolt_pull('origin');"
[ "$status" -eq 0 ]
run query_server_for_db cloned -t -c "SELECT id, label, feeling::text FROM items ORDER BY id;"
[ "$status" -eq 0 ]
[[ "$output" =~ "1 | apple" ]] || false
[[ "$output" =~ "happy" ]] || false
[[ "$output" =~ "2 | banana" ]] || false
[[ "$output" =~ "sad" ]] || false
[[ "$output" =~ "3 | cherry" ]] || false
[[ "$output" =~ "ok" ]] || false
# The function keeps working after an incremental pull too, not just right after clone.
run query_server_for_db cloned -c "SELECT double_it(10);"
[ "$status" -eq 0 ]
[[ "$output" =~ "20" ]] || false
# The pull must have carried server A's advanced current value (150), not left the clone's own.
run query_server_for_db cloned -c "SELECT last_value FROM pg_sequences WHERE sequencename = 'counter';"
[ "$status" -eq 0 ]
[[ "$output" =~ "150" ]] || false
# No further pull happens after this, so it's now safe to call nextval() directly: must
# continue from 150 (next is 200), proving the synced state drives future values correctly too.
run query_server_for_db cloned -c "SELECT nextval('counter');"
[ "$status" -eq 0 ]
[[ "$output" =~ "200" ]] || false
stop_sql_server
cd ..
}