1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-12 10:04:14 +02:00

Refactor of pq shim to allow more flexible scripting.

The pq scripts were pretty static which had already led to a lot of code duplication in the backup test harness.

Instead allow the scripts to be built dynamically, which allows for much more flexibility and reduces duplication. For now just make these changes in the backup harness, but they may be useful elsewhere.

While we are making big changes, also update the macro/function names to hew closer to our current harness naming conventions.
This commit is contained in:
David Steele 2023-10-22 13:55:56 -04:00
parent 306fdff93a
commit e0f5880b09
11 changed files with 1247 additions and 1497 deletions

View File

@ -509,17 +509,13 @@ HRN_FORK_END();
A PostgreSQL libpq shim is provided to simulate interactions with PostgreSQL. Below is a simple example. See [harnessPq.h](https://github.com/pgbackrest/pgbackrest/blob/main/test/src/common/harnessPq.h) for more details.
```
// Set up two standbys but no primary
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_96, "/pgdata", true, NULL, NULL),
HRNPQ_MACRO_OPEN_GE_96(8, "dbname='postgres' port=5433", PG_VERSION_96, "/pgdata", true, NULL, NULL),
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_96, "/pgdata", true, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_96(8, "dbname='postgres' port=5433", PG_VERSION_96, "/pgdata", true, NULL, NULL),
// Close the "inner" session first (8) then the outer (1)
HRNPQ_MACRO_CLOSE(8),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(8),
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ERROR(cmdCheck(), ConfigError, "primary database not found\nHINT: check indexed pg-path/pg-host configurations");
```

View File

@ -571,17 +571,13 @@ HRN_FORK_END();
<code-block>
// Set up two standbys but no primary
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_96, "/pgdata", true, NULL, NULL),
HRNPQ_MACRO_OPEN_GE_96(8, "dbname='postgres' port=5433", PG_VERSION_96, "/pgdata", true, NULL, NULL),
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_96, "/pgdata", true, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_96(8, "dbname='postgres' port=5433", PG_VERSION_96, "/pgdata", true, NULL, NULL),
// Close the "inner" session first (8) then the outer (1)
HRNPQ_MACRO_CLOSE(8),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(8),
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ERROR(cmdCheck(), ConfigError, "primary database not found\nHINT: check indexed pg-path/pg-host configurations");
</code-block>

View File

@ -48,305 +48,186 @@ hrnCmdBackup(void)
void
hrnBackupPqScript(const unsigned int pgVersion, const time_t backupTimeStart, HrnBackupPqScriptParam param)
{
const char *const pg1Path = zNewFmt("%s/pg1", testPath());
const char *const pg2Path = zNewFmt("%s/pg2", testPath());
// If no timeline specified then use timeline 1
param.timeline = param.timeline == 0 ? 1 : param.timeline;
// Read pg_control to get info about the cluster
PgControl pgControl = pgControlFromFile(storagePg(), param.pgVersionForce);
// Set archive timeout really small to save time on errors
cfgOptionSet(cfgOptArchiveTimeout, cfgSourceParam, varNewInt64(100));
// Set LSN and WAL start/stop
uint64_t lsnStart = ((uint64_t)backupTimeStart & 0xFFFFFF00) << 28;
uint64_t lsnStop =
lsnStart + ((uint64_t)(param.walTotal == 0 ? 0 : param.walTotal - 1) * (uint64_t)pgControl.walSegmentSize) +
(uint64_t)(pgControl.walSegmentSize / 2);
const char *walSegmentPrior = strZ(
pgLsnToWalSegment(param.timeline, lsnStart - pgControl.walSegmentSize, pgControl.walSegmentSize));
const char *lsnStartStr = strZ(pgLsnToStr(lsnStart));
const char *walSegmentStart = strZ(pgLsnToWalSegment(param.timeline, lsnStart, pgControl.walSegmentSize));
const char *lsnStopStr = strZ(pgLsnToStr(lsnStop));
const char *walSegmentStop = strZ(pgLsnToWalSegment(param.timeline, lsnStop, pgControl.walSegmentSize));
// Save pg_control with updated info
pgControl.checkpoint = lsnStart;
pgControl.timeline = param.timeline;
HRN_STORAGE_PUT(
storagePgIdxWrite(0), PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL, hrnPgControlToBuffer(0, 0, pgControl),
.timeModified = backupTimeStart);
// Update pg_control on primary with the backup time
HRN_PG_CONTROL_TIME(storagePgIdxWrite(0), backupTimeStart);
// Write WAL segments to the archive
// -----------------------------------------------------------------------------------------------------------------------------
if (!param.noPriorWal)
MEM_CONTEXT_TEMP_BEGIN()
{
InfoArchive *infoArchive = infoArchiveLoadFile(
storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, param.cipherType == 0 ? cipherTypeNone : param.cipherType,
param.cipherPass == NULL ? NULL : STR(param.cipherPass));
const String *archiveId = infoArchiveId(infoArchive);
StringList *walSegmentList = pgLsnRangeToWalSegmentList(
param.timeline, lsnStart - pgControl.walSegmentSize, param.noWal ? lsnStart - pgControl.walSegmentSize : lsnStop,
pgControl.walSegmentSize);
const char *const pg1Path = zNewFmt("%s/pg1", testPath());
const char *const pg2Path = zNewFmt("%s/pg2", testPath());
Buffer *walBuffer = bufNew((size_t)pgControl.walSegmentSize);
bufUsedSet(walBuffer, bufSize(walBuffer));
memset(bufPtr(walBuffer), 0, bufSize(walBuffer));
HRN_PG_WAL_TO_BUFFER(walBuffer, pgControl.version, .systemId = pgControl.systemId);
const String *walChecksum = strNewEncode(encodingHex, cryptoHashOne(hashTypeSha1, walBuffer));
// If no timeline specified then use timeline 1
param.timeline = param.timeline == 0 ? 1 : param.timeline;
for (unsigned int walSegmentIdx = 0; walSegmentIdx < strLstSize(walSegmentList); walSegmentIdx++)
{
MEM_CONTEXT_TEMP_BEGIN()
{
StorageWrite *write = storageNewWriteP(
storageRepoWrite(),
strNewFmt(
STORAGE_REPO_ARCHIVE "/%s/%s-%s%s", strZ(archiveId), strZ(strLstGet(walSegmentList, walSegmentIdx)),
strZ(walChecksum), strZ(compressExtStr(param.walCompressType))));
// Read pg_control to get info about the cluster
PgControl pgControl = pgControlFromFile(storagePg(), param.pgVersionForce);
if (param.walCompressType != compressTypeNone)
ioFilterGroupAdd(ioWriteFilterGroup(storageWriteIo(write)), compressFilterP(param.walCompressType, 1));
// Set archive timeout really small to save time on errors
cfgOptionSet(cfgOptArchiveTimeout, cfgSourceParam, varNewInt64(100));
storagePutP(write, walBuffer);
}
MEM_CONTEXT_TEMP_END();
}
}
// Set LSN and WAL start/stop
uint64_t lsnStart = ((uint64_t)backupTimeStart & 0xFFFFFF00) << 28;
uint64_t lsnStop =
lsnStart + ((uint64_t)(param.walTotal == 0 ? 0 : param.walTotal - 1) * (uint64_t)pgControl.walSegmentSize) +
(uint64_t)(pgControl.walSegmentSize / 2);
// -----------------------------------------------------------------------------------------------------------------------------
if (pgVersion == PG_VERSION_95)
{
ASSERT(!param.backupStandby);
ASSERT(!param.errorAfterStart);
if (param.noArchiveCheck)
{
harnessPqScriptSet((HarnessPq [])
{
// Connect to primary
HRNPQ_MACRO_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_95, pg1Path, false, NULL, NULL),
// Get start time
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000),
// Start backup
HRNPQ_MACRO_ADVISORY_LOCK(1, true),
HRNPQ_MACRO_IS_IN_BACKUP(1, false),
HRNPQ_MACRO_START_BACKUP_LE_95(1, param.startFast, lsnStartStr, walSegmentStart),
HRNPQ_MACRO_DATABASE_LIST_1(1, "test1"),
HRNPQ_MACRO_TABLESPACE_LIST_0(1),
// Get copy start time
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000 + 999),
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000 + 1000),
// Ping
HRNPQ_MACRO_IS_STANDBY_QUERY(1, false),
HRNPQ_MACRO_IS_STANDBY_QUERY(1, false),
// Stop backup
HRNPQ_MACRO_STOP_BACKUP_LE_95(1, lsnStopStr, walSegmentStop),
// Get stop time
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000 + 52427000),
HRNPQ_MACRO_DONE()
});
}
else
{
harnessPqScriptSet((HarnessPq [])
{
// Connect to primary
HRNPQ_MACRO_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_95, pg1Path, false, NULL, NULL),
// Get start time
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000),
// Start backup
HRNPQ_MACRO_ADVISORY_LOCK(1, true),
HRNPQ_MACRO_IS_IN_BACKUP(1, false),
HRNPQ_MACRO_CURRENT_WAL_LE_96(1, walSegmentPrior),
HRNPQ_MACRO_START_BACKUP_LE_95(1, param.startFast, lsnStartStr, walSegmentStart),
HRNPQ_MACRO_DATABASE_LIST_1(1, "test1"),
HRNPQ_MACRO_TABLESPACE_LIST_0(1),
// Get copy start time
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000 + 999),
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000 + 1000),
// Ping
HRNPQ_MACRO_IS_STANDBY_QUERY(1, false),
HRNPQ_MACRO_IS_STANDBY_QUERY(1, false),
// Stop backup
HRNPQ_MACRO_STOP_BACKUP_LE_95(1, lsnStopStr, walSegmentStop),
// Get stop time
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000 + 2000),
HRNPQ_MACRO_DONE()
});
}
}
// -----------------------------------------------------------------------------------------------------------------------------
else if (pgVersion == PG_VERSION_96)
{
ASSERT(param.backupStandby);
ASSERT(!param.errorAfterStart);
ASSERT(!param.noArchiveCheck);
const char *walSegmentPrior = strZ(
pgLsnToWalSegment(param.timeline, lsnStart - pgControl.walSegmentSize, pgControl.walSegmentSize));
const char *lsnStartStr = strZ(pgLsnToStr(lsnStart));
const char *walSegmentStart = strZ(pgLsnToWalSegment(param.timeline, lsnStart, pgControl.walSegmentSize));
const char *lsnStopStr = strZ(pgLsnToStr(lsnStop));
const char *walSegmentStop = strZ(pgLsnToWalSegment(param.timeline, lsnStop, pgControl.walSegmentSize));
// Save pg_control with updated info
HRN_STORAGE_PUT(storagePgIdxWrite(1), PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL, hrnPgControlToBuffer(0, 0, pgControl));
pgControl.checkpoint = lsnStart;
pgControl.timeline = param.timeline;
if (param.noPriorWal)
HRN_STORAGE_PUT(
storagePgIdxWrite(0), PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL, hrnPgControlToBuffer(0, 0, pgControl),
.timeModified = backupTimeStart);
// Update pg_control on primary with the backup time
HRN_PG_CONTROL_TIME(storagePgIdxWrite(0), backupTimeStart);
// Write WAL segments to the archive
// -------------------------------------------------------------------------------------------------------------------------
if (!param.noPriorWal)
{
harnessPqScriptSet((HarnessPq [])
InfoArchive *infoArchive = infoArchiveLoadFile(
storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, param.cipherType == 0 ? cipherTypeNone : param.cipherType,
param.cipherPass == NULL ? NULL : STR(param.cipherPass));
const String *archiveId = infoArchiveId(infoArchive);
StringList *walSegmentList = pgLsnRangeToWalSegmentList(
param.timeline, lsnStart - pgControl.walSegmentSize, param.noWal ? lsnStart - pgControl.walSegmentSize : lsnStop,
pgControl.walSegmentSize);
Buffer *walBuffer = bufNew((size_t)pgControl.walSegmentSize);
bufUsedSet(walBuffer, bufSize(walBuffer));
memset(bufPtr(walBuffer), 0, bufSize(walBuffer));
HRN_PG_WAL_TO_BUFFER(walBuffer, pgControl.version, .systemId = pgControl.systemId);
const String *walChecksum = strNewEncode(encodingHex, cryptoHashOne(hashTypeSha1, walBuffer));
for (unsigned int walSegmentIdx = 0; walSegmentIdx < strLstSize(walSegmentList); walSegmentIdx++)
{
// Connect to primary
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_96, pg1Path, false, NULL, NULL),
MEM_CONTEXT_TEMP_BEGIN()
{
StorageWrite *write = storageNewWriteP(
storageRepoWrite(),
strNewFmt(
STORAGE_REPO_ARCHIVE "/%s/%s-%s%s", strZ(archiveId), strZ(strLstGet(walSegmentList, walSegmentIdx)),
strZ(walChecksum), strZ(compressExtStr(param.walCompressType))));
// Connect to standby
HRNPQ_MACRO_OPEN_GE_96(2, "dbname='postgres' port=5433", PG_VERSION_96, pg2Path, true, NULL, NULL),
if (param.walCompressType != compressTypeNone)
ioFilterGroupAdd(ioWriteFilterGroup(storageWriteIo(write)), compressFilterP(param.walCompressType, 1));
// Get start time
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000),
// Start backup
HRNPQ_MACRO_ADVISORY_LOCK(1, true),
HRNPQ_MACRO_CURRENT_WAL_LE_96(1, walSegmentPrior),
HRNPQ_MACRO_START_BACKUP_96(1, true, lsnStartStr, walSegmentStart),
HRNPQ_MACRO_DATABASE_LIST_1(1, "test1"),
HRNPQ_MACRO_TABLESPACE_LIST_0(1),
// Wait for standby to sync
HRNPQ_MACRO_REPLAY_WAIT_96(2, lsnStartStr),
HRNPQ_MACRO_DONE()
});
storagePutP(write, walBuffer);
}
MEM_CONTEXT_TEMP_END();
}
}
// Generate pq script
// -------------------------------------------------------------------------------------------------------------------------
// Connect to primary
if (pgVersion <= PG_VERSION_95)
HRN_PQ_SCRIPT_SET(HRN_PQ_SCRIPT_OPEN_GE_93(1, "dbname='postgres' port=5432", pgVersion, pg1Path, false, NULL, NULL));
else
HRN_PQ_SCRIPT_SET(HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", pgVersion, pg1Path, false, NULL, NULL));
// Connect to standby
if (param.backupStandby)
{
harnessPqScriptSet((HarnessPq [])
// Save standby pg_control with updated info
HRN_STORAGE_PUT(storagePgIdxWrite(1), PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL, hrnPgControlToBuffer(0, 0, pgControl));
if (pgVersion <= PG_VERSION_95)
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_OPEN_GE_93(2, "dbname='postgres' port=5433", pgVersion, pg2Path, true, NULL, NULL));
else
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_OPEN_GE_96(2, "dbname='postgres' port=5433", pgVersion, pg2Path, true, NULL, NULL));
}
// Get start time
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_TIME_QUERY(1, (int64_t)backupTimeStart * 1000));
// Advisory lock
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_ADVISORY_LOCK(1, true));
// Check if backup is in progress (only for exclusive backup)
if (pgVersion <= PG_VERSION_95)
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_IS_IN_BACKUP(1, false));
// Perform archive check
if (!param.noArchiveCheck)
{
const char *const walSegment = param.walSwitch ? walSegmentStart : walSegmentPrior;
if (pgVersion <= PG_VERSION_96)
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_CURRENT_WAL_LE_96(1, walSegment));
else
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_CURRENT_WAL_GE_10(1, walSegment));
}
// Start backup
if (pgVersion <= PG_VERSION_95)
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_START_BACKUP_LE_95(1, param.startFast, lsnStartStr, walSegmentStart));
else if (pgVersion <= PG_VERSION_96)
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_START_BACKUP_96(1, param.startFast, lsnStartStr, walSegmentStart));
else
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_START_BACKUP_GE_10(1, param.startFast, lsnStartStr, walSegmentStart));
// Switch WAL segment so it can be checked
if (param.walSwitch)
{
HRN_PQ_SCRIPT_ADD(
HRN_PQ_SCRIPT_CREATE_RESTORE_POINT(1, "X/X"),
HRN_PQ_SCRIPT_WAL_SWITCH(1, "wal", walSegmentStart));
}
// Get database list
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_DATABASE_LIST_1(1, "test1"));
// Get tablespace list
if (param.tablespace)
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_TABLESPACE_LIST_1(1, 32768, "tblspc32768"));
else
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_TABLESPACE_LIST_0(1));
// Wait for standby to sync
if (param.backupStandby)
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_REPLAY_WAIT_96(2, lsnStartStr));
// Continue if WAL check succeeds
if (!param.noPriorWal)
{
// Get copy start time
HRN_PQ_SCRIPT_ADD(
HRN_PQ_SCRIPT_TIME_QUERY(1, (int64_t)backupTimeStart * 1000 + 999),
HRN_PQ_SCRIPT_TIME_QUERY(1, (int64_t)backupTimeStart * 1000 + 1000));
// Continue if there is no error after start
if (!param.errorAfterStart)
{
// Connect to primary
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_96, pg1Path, false, NULL, NULL),
// Ping to check standby mode
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_IS_STANDBY_QUERY(1, false));
// Connect to standby
HRNPQ_MACRO_OPEN_GE_96(2, "dbname='postgres' port=5433", PG_VERSION_96, pg2Path, true, NULL, NULL),
if (param.backupStandby)
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_IS_STANDBY_QUERY(2, true));
// Get start time
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000),
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_IS_STANDBY_QUERY(1, false));
// Start backup
HRNPQ_MACRO_ADVISORY_LOCK(1, true),
HRNPQ_MACRO_CURRENT_WAL_LE_96(1, walSegmentPrior),
HRNPQ_MACRO_START_BACKUP_96(1, true, lsnStartStr, walSegmentStart),
HRNPQ_MACRO_DATABASE_LIST_1(1, "test1"),
HRNPQ_MACRO_TABLESPACE_LIST_0(1),
// Wait for standby to sync
HRNPQ_MACRO_REPLAY_WAIT_96(2, lsnStartStr),
// Get copy start time
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000 + 999),
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000 + 1000),
// Ping
HRNPQ_MACRO_IS_STANDBY_QUERY(1, false),
HRNPQ_MACRO_IS_STANDBY_QUERY(2, true),
HRNPQ_MACRO_IS_STANDBY_QUERY(1, false),
HRNPQ_MACRO_IS_STANDBY_QUERY(2, true),
if (param.backupStandby)
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_IS_STANDBY_QUERY(2, true));
// Stop backup
HRNPQ_MACRO_STOP_BACKUP_96(1, lsnStopStr, walSegmentStop, false),
if (pgVersion <= PG_VERSION_95)
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_STOP_BACKUP_LE_95(1, lsnStopStr, walSegmentStop));
else if (pgVersion <= PG_VERSION_96)
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_STOP_BACKUP_96(1, lsnStopStr, walSegmentStop, false));
else
HRN_PQ_SCRIPT_ADD(HRN_PQ_SCRIPT_STOP_BACKUP_GE_10(1, lsnStopStr, walSegmentStop, true));
// Get stop time
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000 + 2000),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_ADD(
HRN_PQ_SCRIPT_TIME_QUERY(1, ((int64_t)backupTimeStart + (param.noArchiveCheck ? 52427 : 2)) * 1000));
}
}
}
// -----------------------------------------------------------------------------------------------------------------------------
else if (pgVersion == PG_VERSION_11)
{
ASSERT(!param.backupStandby);
ASSERT(!param.noArchiveCheck);
if (param.errorAfterStart)
{
harnessPqScriptSet((HarnessPq [])
{
// Connect to primary
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_11, pg1Path, false, NULL, NULL),
// Get start time
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000),
// Start backup
HRNPQ_MACRO_ADVISORY_LOCK(1, true),
HRNPQ_MACRO_CURRENT_WAL_GE_10(1, walSegmentPrior),
HRNPQ_MACRO_START_BACKUP_GE_10(1, param.startFast, lsnStartStr, walSegmentStart),
HRNPQ_MACRO_DATABASE_LIST_1(1, "test1"),
HRNPQ_MACRO_TABLESPACE_LIST_1(1, 32768, "tblspc32768"),
// Get copy start time
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000 + 999),
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000 + 1000),
HRNPQ_MACRO_DONE()
});
}
else
{
harnessPqScriptSet((HarnessPq [])
{
// Connect to primary
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_11, pg1Path, false, NULL, NULL),
// Get start time
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000),
// Start backup
HRNPQ_MACRO_ADVISORY_LOCK(1, true),
HRNPQ_MACRO_CURRENT_WAL_GE_10(1, walSegmentStart),
HRNPQ_MACRO_START_BACKUP_GE_10(1, param.startFast, lsnStartStr, walSegmentStart),
// Switch WAL segment so it can be checked
HRNPQ_MACRO_CREATE_RESTORE_POINT(1, "X/X"),
HRNPQ_MACRO_WAL_SWITCH(1, "wal", walSegmentStart),
// Get database and tablespace list
HRNPQ_MACRO_DATABASE_LIST_1(1, "test1"),
HRNPQ_MACRO_TABLESPACE_LIST_1(1, 32768, "tblspc32768"),
// Get copy start time
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000 + 999),
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000 + 1000),
// Ping
HRNPQ_MACRO_IS_STANDBY_QUERY(1, false),
HRNPQ_MACRO_IS_STANDBY_QUERY(1, false),
// Stop backup
HRNPQ_MACRO_STOP_BACKUP_GE_10(1, lsnStopStr, walSegmentStop, true),
// Get stop time
HRNPQ_MACRO_TIME_QUERY(1, (int64_t)backupTimeStart * 1000 + 2000),
HRNPQ_MACRO_DONE()
});
}
}
else
THROW_FMT(AssertError, "unsupported test version %u", pgVersion); // {uncoverable - no invalid versions in tests}
MEM_CONTEXT_TEMP_END();
}

View File

@ -26,6 +26,8 @@ typedef struct HrnBackupPqScriptParam
bool noWal; // Don't write test WAL segments
bool noPriorWal; // Don't write prior test WAL segments
bool noArchiveCheck; // Do not check archive
bool walSwitch; // WAL switch is required
bool tablespace; // Is there a tablespace?
CompressType walCompressType; // Compress type for the archive files
CipherType cipherType; // Cipher type
const char *cipherPass; // Cipher pass

View File

@ -22,62 +22,93 @@ Pq shim error prefix
#define PQ_ERROR_PREFIX "PQ SHIM ERROR"
/***********************************************************************************************************************************
Script that defines how shim functions operate
Local variables
***********************************************************************************************************************************/
HarnessPq harnessPqScript[1024];
bool harnessPqScriptDone = true;
unsigned int harnessPqScriptIdx;
// Is PQfinish scripting required?
bool harnessPqStrict = false;
// If there is a script failure change the behavior of cleanup functions to return immediately so the real error will be reported
// rather than a bogus scripting error during cleanup
bool harnessPqScriptFail;
char harnessPqScriptError[4096];
/***********************************************************************************************************************************
Set pq script
***********************************************************************************************************************************/
void
harnessPqScriptSet(HarnessPq *harnessPqScriptParam)
static struct HrnPqLocal
{
if (!harnessPqScriptDone)
MemContext *memContext; // Script mem context
// Script that defines how shim functions operate
HrnPqScript script[1024];
unsigned int scriptSize;
unsigned int scriptIdx;
// Is PQfinish scripting required?
bool strict;
// If there is a script failure change the behavior of cleanup functions to return immediately so the real error will be
// reported rather than a bogus scripting error during cleanup
bool scriptFail;
char scriptError[4096];
} hrnPqLocal;
/**********************************************************************************************************************************/
void
hrnPqScriptSet(const HrnPqScript *const script, const unsigned int scriptSize)
{
if (hrnPqLocal.scriptSize != 0)
THROW(AssertError, "previous pq script has not yet completed");
if (harnessPqScriptParam[0].function == NULL)
THROW(AssertError, "pq script must have entries");
// Copy records into local storage
unsigned int copyIdx = 0;
while (harnessPqScriptParam[copyIdx].function != NULL)
{
harnessPqScript[copyIdx] = harnessPqScriptParam[copyIdx];
copyIdx++;
}
harnessPqScript[copyIdx].function = NULL;
harnessPqScriptDone = false;
harnessPqScriptIdx = 0;
hrnPqScriptAdd(script, scriptSize);
}
/**********************************************************************************************************************************/
void
harnessPqScriptStrictSet(bool strict)
hrnPqScriptAdd(const HrnPqScript *const script, const unsigned int scriptSize)
{
harnessPqStrict = strict;
if (scriptSize == 0)
THROW(AssertError, "pq script must have entries");
if (hrnPqLocal.scriptSize == 0)
{
MEM_CONTEXT_BEGIN(memContextTop())
{
MEM_CONTEXT_NEW_BEGIN(HrnPqLocal, .childQty = MEM_CONTEXT_QTY_MAX)
{
hrnPqLocal.memContext = MEM_CONTEXT_NEW();
}
MEM_CONTEXT_NEW_END();
}
MEM_CONTEXT_END();
hrnPqLocal.scriptIdx = 0;
}
// Copy records into local storage
MEM_CONTEXT_BEGIN(hrnPqLocal.memContext)
{
for (unsigned int scriptIdx = 0; scriptIdx < scriptSize; scriptIdx++)
{
hrnPqLocal.script[hrnPqLocal.scriptSize] = script[scriptIdx];
if (script[scriptIdx].param != NULL)
hrnPqLocal.script[hrnPqLocal.scriptSize].param = strZ(strNewZ(script[scriptIdx].param));
if (script[scriptIdx].resultZ != NULL)
hrnPqLocal.script[hrnPqLocal.scriptSize].resultZ = strZ(strNewZ(script[scriptIdx].resultZ));
hrnPqLocal.scriptSize++;
}
}
MEM_CONTEXT_END();
}
/**********************************************************************************************************************************/
void
hrnPqScriptStrictSet(bool strict)
{
hrnPqLocal.strict = strict;
}
/***********************************************************************************************************************************
Run pq script
***********************************************************************************************************************************/
static HarnessPq *
harnessPqScriptRun(const char *const function, const VariantList *const param, const HarnessPq *const parent)
static HrnPqScript *
hrnPqScriptRun(const char *const function, const VariantList *const param, const HrnPqScript *const parent)
{
// If an error has already been thrown then throw the same error again
if (harnessPqScriptFail)
THROW(AssertError, harnessPqScriptError);
if (hrnPqLocal.scriptFail)
THROW(AssertError, hrnPqLocal.scriptError);
// Convert params to json for comparison and reporting
String *paramStr = NULL;
@ -93,36 +124,37 @@ harnessPqScriptRun(const char *const function, const VariantList *const param, c
paramStr = strNew();
// Ensure script has not ended
if (harnessPqScriptDone)
if (hrnPqLocal.scriptSize == 0)
{
snprintf(harnessPqScriptError, sizeof(harnessPqScriptError), "pq script ended before %s (%s)", function, strZ(paramStr));
snprintf(
hrnPqLocal.scriptError, sizeof(hrnPqLocal.scriptError), "pq script ended before %s (%s)", function, strZ(paramStr));
TEST_LOG_FMT(PQ_ERROR_PREFIX ": %s", harnessPqScriptError);
harnessPqScriptFail = true;
TEST_LOG_FMT(PQ_ERROR_PREFIX ": %s", hrnPqLocal.scriptError);
hrnPqLocal.scriptFail = true;
THROW(AssertError, harnessPqScriptError);
THROW(AssertError, hrnPqLocal.scriptError);
}
// Get current script item
HarnessPq *result = &harnessPqScript[harnessPqScriptIdx];
HrnPqScript *const result = &hrnPqLocal.script[hrnPqLocal.scriptIdx];
// Check that expected function was called
if (strcmp(result->function, function) != 0)
{
snprintf(
harnessPqScriptError, sizeof(harnessPqScriptError), "pq script [%u] expected function %s (%s) but got %s (%s)",
harnessPqScriptIdx, result->function, result->param == NULL ? "" : result->param, function, strZ(paramStr));
hrnPqLocal.scriptError, sizeof(hrnPqLocal.scriptError), "pq script [%u] expected function %s (%s) but got %s (%s)",
hrnPqLocal.scriptIdx, result->function, result->param == NULL ? "" : result->param, function, strZ(paramStr));
TEST_LOG_FMT(PQ_ERROR_PREFIX ": %s", harnessPqScriptError);
harnessPqScriptFail = true;
TEST_LOG_FMT(PQ_ERROR_PREFIX ": %s", hrnPqLocal.scriptError);
hrnPqLocal.scriptFail = true;
// Return without error if closing the connection and an error is currently being thrown. Errors outside of the pq shim can
// cause the connection to be cleaned up and we don't want to mask those errors. However, the failure is still logged and
// any subsequent call to the pq shim will result in an error.
if (strcmp(function, HRNPQ_FINISH) == 0 && errorType() != NULL)
if (strcmp(function, HRN_PQ_FINISH) == 0 && errorType() != NULL)
return NULL;
THROW(AssertError, harnessPqScriptError);
THROW(AssertError, hrnPqLocal.scriptError);
}
// Check that parameters match
@ -130,38 +162,42 @@ harnessPqScriptRun(const char *const function, const VariantList *const param, c
(param != NULL && result->param != NULL && !strEqZ(paramStr, result->param)))
{
snprintf(
harnessPqScriptError, sizeof(harnessPqScriptError), "pq script [%u] function '%s', expects param '%s' but got '%s'",
harnessPqScriptIdx, result->function, result->param ? result->param : "NULL", param ? strZ(paramStr) : "NULL");
hrnPqLocal.scriptError, sizeof(hrnPqLocal.scriptError), "pq script [%u] function '%s', expects param '%s' but got '%s'",
hrnPqLocal.scriptIdx, result->function, result->param ? result->param : "NULL", param ? strZ(paramStr) : "NULL");
TEST_LOG_FMT(PQ_ERROR_PREFIX ": %s", harnessPqScriptError);
harnessPqScriptFail = true;
TEST_LOG_FMT(PQ_ERROR_PREFIX ": %s", hrnPqLocal.scriptError);
hrnPqLocal.scriptFail = true;
THROW(AssertError, harnessPqScriptError);
THROW(AssertError, hrnPqLocal.scriptError);
}
// Make sure the session matches with the parent as a sanity check
if (parent != NULL && result->session != parent->session)
{
snprintf(
harnessPqScriptError, sizeof(harnessPqScriptError), "pq script [%u] function '%s', expects session '%u' but got '%u'",
harnessPqScriptIdx, result->function, result->session, parent->session);
hrnPqLocal.scriptError, sizeof(hrnPqLocal.scriptError),
"pq script [%u] function '%s', expects session '%u' but got '%u'", hrnPqLocal.scriptIdx, result->function,
result->session, parent->session);
TEST_LOG_FMT(PQ_ERROR_PREFIX ": %s", harnessPqScriptError);
harnessPqScriptFail = true;
TEST_LOG_FMT(PQ_ERROR_PREFIX ": %s", hrnPqLocal.scriptError);
hrnPqLocal.scriptFail = true;
THROW(AssertError, harnessPqScriptError);
THROW(AssertError, hrnPqLocal.scriptError);
}
strFree(paramStr);
// Sleep if requested
if (result->sleep > 0)
sleepMSec(result->sleep);
harnessPqScriptIdx++;
hrnPqLocal.scriptIdx++;
if (harnessPqScript[harnessPqScriptIdx].function == NULL)
harnessPqScriptDone = true;
strFree(paramStr);
if (hrnPqLocal.scriptIdx == hrnPqLocal.scriptSize)
{
memContextFree(hrnPqLocal.memContext);
hrnPqLocal.scriptSize = 0;
}
return result;
}
@ -172,7 +208,7 @@ Shim for PQconnectdb()
PGconn *
PQconnectdb(const char *conninfo)
{
return (PGconn *)harnessPqScriptRun(HRNPQ_CONNECTDB, varLstAdd(varLstNew(), varNewStrZ(conninfo)), NULL);
return (PGconn *)hrnPqScriptRun(HRN_PQ_CONNECTDB, varLstAdd(varLstNew(), varNewStrZ(conninfo)), NULL);
}
/***********************************************************************************************************************************
@ -181,7 +217,7 @@ Shim for PQstatus()
ConnStatusType
PQstatus(const PGconn *conn)
{
return (ConnStatusType)harnessPqScriptRun(HRNPQ_STATUS, NULL, (HarnessPq *)conn)->resultInt;
return (ConnStatusType)hrnPqScriptRun(HRN_PQ_STATUS, NULL, (HrnPqScript *)conn)->resultInt;
}
/***********************************************************************************************************************************
@ -190,7 +226,7 @@ Shim for PQerrorMessage()
char *
PQerrorMessage(const PGconn *conn)
{
return (char *)harnessPqScriptRun(HRNPQ_ERRORMESSAGE, NULL, (HarnessPq *)conn)->resultZ;
return (char *)hrnPqScriptRun(HRN_PQ_ERRORMESSAGE, NULL, (HrnPqScript *)conn)->resultZ;
}
/***********************************************************************************************************************************
@ -212,7 +248,7 @@ Shim for PQsendQuery()
int
PQsendQuery(PGconn *conn, const char *query)
{
return harnessPqScriptRun(HRNPQ_SENDQUERY, varLstAdd(varLstNew(), varNewStrZ(query)), (HarnessPq *)conn)->resultInt;
return hrnPqScriptRun(HRN_PQ_SENDQUERY, varLstAdd(varLstNew(), varNewStrZ(query)), (HrnPqScript *)conn)->resultInt;
}
/***********************************************************************************************************************************
@ -221,7 +257,7 @@ Shim for PQconsumeInput()
int
PQconsumeInput(PGconn *conn)
{
return harnessPqScriptRun(HRNPQ_CONSUMEINPUT, NULL, (HarnessPq *)conn)->resultInt;
return hrnPqScriptRun(HRN_PQ_CONSUMEINPUT, NULL, (HrnPqScript *)conn)->resultInt;
}
/***********************************************************************************************************************************
@ -230,7 +266,7 @@ Shim for PQisBusy()
int
PQisBusy(PGconn *conn)
{
return harnessPqScriptRun(HRNPQ_ISBUSY, NULL, (HarnessPq *)conn)->resultInt;
return hrnPqScriptRun(HRN_PQ_ISBUSY, NULL, (HrnPqScript *)conn)->resultInt;
}
/***********************************************************************************************************************************
@ -239,8 +275,8 @@ Shim for PQgetCancel()
PGcancel *
PQgetCancel(PGconn *conn)
{
HarnessPq *harnessPq = harnessPqScriptRun(HRNPQ_GETCANCEL, NULL, (HarnessPq *)conn);
return harnessPq->resultNull ? NULL : (PGcancel *)harnessPq;
HrnPqScript *const hrnPq = hrnPqScriptRun(HRN_PQ_GETCANCEL, NULL, (HrnPqScript *)conn);
return hrnPq->resultNull ? NULL : (PGcancel *)hrnPq;
}
/***********************************************************************************************************************************
@ -249,15 +285,15 @@ Shim for PQcancel()
int
PQcancel(PGcancel *cancel, char *errbuf, int errbufsize)
{
HarnessPq *harnessPq = harnessPqScriptRun(HRNPQ_CANCEL, NULL, (HarnessPq *)cancel);
HrnPqScript *const hrnPq = hrnPqScriptRun(HRN_PQ_CANCEL, NULL, (HrnPqScript *)cancel);
if (!harnessPq->resultInt)
if (!hrnPq->resultInt)
{
strncpy(errbuf, harnessPq->resultZ, (size_t)errbufsize);
strncpy(errbuf, hrnPq->resultZ, (size_t)errbufsize);
errbuf[errbufsize - 1] = '\0';
}
return harnessPq->resultInt;
return hrnPq->resultInt;
}
/***********************************************************************************************************************************
@ -266,7 +302,7 @@ Shim for PQfreeCancel()
void
PQfreeCancel(PGcancel *cancel)
{
harnessPqScriptRun(HRNPQ_FREECANCEL, NULL, (HarnessPq *)cancel);
hrnPqScriptRun(HRN_PQ_FREECANCEL, NULL, (HrnPqScript *)cancel);
}
/***********************************************************************************************************************************
@ -275,10 +311,10 @@ Shim for PQgetResult()
PGresult *
PQgetResult(PGconn *conn)
{
if (!harnessPqScriptFail)
if (!hrnPqLocal.scriptFail)
{
HarnessPq *harnessPq = harnessPqScriptRun(HRNPQ_GETRESULT, NULL, (HarnessPq *)conn);
return harnessPq->resultNull ? NULL : (PGresult *)harnessPq;
HrnPqScript *const hrnPq = hrnPqScriptRun(HRN_PQ_GETRESULT, NULL, (HrnPqScript *)conn);
return hrnPq->resultNull ? NULL : (PGresult *)hrnPq;
}
return NULL;
@ -290,7 +326,7 @@ Shim for PQresultStatus()
ExecStatusType
PQresultStatus(const PGresult *res)
{
return (ExecStatusType)harnessPqScriptRun(HRNPQ_RESULTSTATUS, NULL, (HarnessPq *)res)->resultInt;
return (ExecStatusType)hrnPqScriptRun(HRN_PQ_RESULTSTATUS, NULL, (HrnPqScript *)res)->resultInt;
}
/***********************************************************************************************************************************
@ -299,7 +335,7 @@ Shim for PQresultErrorMessage()
char *
PQresultErrorMessage(const PGresult *res)
{
return (char *)harnessPqScriptRun(HRNPQ_RESULTERRORMESSAGE, NULL, (HarnessPq *)res)->resultZ;
return (char *)hrnPqScriptRun(HRN_PQ_RESULTERRORMESSAGE, NULL, (HrnPqScript *)res)->resultZ;
}
/***********************************************************************************************************************************
@ -308,7 +344,7 @@ Shim for PQntuples()
int
PQntuples(const PGresult *res)
{
return harnessPqScriptRun(HRNPQ_NTUPLES, NULL, (HarnessPq *)res)->resultInt;
return hrnPqScriptRun(HRN_PQ_NTUPLES, NULL, (HrnPqScript *)res)->resultInt;
}
/***********************************************************************************************************************************
@ -317,7 +353,7 @@ Shim for PQnfields()
int
PQnfields(const PGresult *res)
{
return harnessPqScriptRun(HRNPQ_NFIELDS, NULL, (HarnessPq *)res)->resultInt;
return hrnPqScriptRun(HRN_PQ_NFIELDS, NULL, (HrnPqScript *)res)->resultInt;
}
/***********************************************************************************************************************************
@ -326,8 +362,9 @@ Shim for PQgetisnull()
int
PQgetisnull(const PGresult *res, int tup_num, int field_num)
{
return harnessPqScriptRun(
HRNPQ_GETISNULL, varLstAdd(varLstAdd(varLstNew(), varNewInt(tup_num)), varNewInt(field_num)), (HarnessPq *)res)->resultInt;
return hrnPqScriptRun(
HRN_PQ_GETISNULL, varLstAdd(varLstAdd(varLstNew(), varNewInt(tup_num)), varNewInt(field_num)),
(HrnPqScript *)res)->resultInt;
}
/***********************************************************************************************************************************
@ -336,7 +373,7 @@ Shim for PQftype()
Oid
PQftype(const PGresult *res, int field_num)
{
return (Oid)harnessPqScriptRun(HRNPQ_FTYPE, varLstAdd(varLstNew(), varNewInt(field_num)), (HarnessPq *)res)->resultInt;
return (Oid)hrnPqScriptRun(HRN_PQ_FTYPE, varLstAdd(varLstNew(), varNewInt(field_num)), (HrnPqScript *)res)->resultInt;
}
/***********************************************************************************************************************************
@ -345,8 +382,8 @@ Shim for PQgetvalue()
char *
PQgetvalue(const PGresult *res, int tup_num, int field_num)
{
return (char *)harnessPqScriptRun(
HRNPQ_GETVALUE, varLstAdd(varLstAdd(varLstNew(), varNewInt(tup_num)), varNewInt(field_num)), (HarnessPq *)res)->resultZ;
return (char *)hrnPqScriptRun(
HRN_PQ_GETVALUE, varLstAdd(varLstAdd(varLstNew(), varNewInt(tup_num)), varNewInt(field_num)), (HrnPqScript *)res)->resultZ;
}
/***********************************************************************************************************************************
@ -355,8 +392,8 @@ Shim for PQclear()
void
PQclear(PGresult *res)
{
if (!harnessPqScriptFail)
harnessPqScriptRun(HRNPQ_CLEAR, NULL, (HarnessPq *)res);
if (!hrnPqLocal.scriptFail)
hrnPqScriptRun(HRN_PQ_CLEAR, NULL, (HrnPqScript *)res);
}
/***********************************************************************************************************************************
@ -365,8 +402,8 @@ Shim for PQfinish()
void
PQfinish(PGconn *conn)
{
if (harnessPqStrict && !harnessPqScriptFail)
harnessPqScriptRun(HRNPQ_FINISH, NULL, (HarnessPq *)conn);
if (hrnPqLocal.strict && !hrnPqLocal.scriptFail)
hrnPqScriptRun(HRN_PQ_FINISH, NULL, (HrnPqScript *)conn);
}
#endif // HARNESS_PQ_REAL

File diff suppressed because it is too large Load Diff

View File

@ -1949,13 +1949,9 @@ testRun(void)
hrnCfgArgRawBool(argList, cfgOptChecksumPage, true);
HRN_CFG_LOAD(cfgCmdBackup, argList);
harnessPqScriptSet((HarnessPq [])
{
HRN_PQ_SCRIPT_SET(
// Connect to primary
HRNPQ_MACRO_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_93, TEST_PATH "/pg1", false, NULL, NULL),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_93, TEST_PATH "/pg1", false, NULL, NULL));
TEST_RESULT_VOID(
dbFree(
@ -1980,13 +1976,9 @@ testRun(void)
hrnCfgArgRawBool(argList, cfgOptChecksumPage, false);
HRN_CFG_LOAD(cfgCmdBackup, argList);
harnessPqScriptSet((HarnessPq [])
{
HRN_PQ_SCRIPT_SET(
// Connect to primary
HRNPQ_MACRO_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_93, TEST_PATH "/pg1", false, NULL, NULL),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_93, TEST_PATH "/pg1", false, NULL, NULL));
TEST_RESULT_VOID(
dbFree(
@ -1997,13 +1989,9 @@ testRun(void)
// Create pg_control without page checksums
HRN_PG_CONTROL_PUT(storagePgWrite(), PG_VERSION_93);
harnessPqScriptSet((HarnessPq [])
{
HRN_PQ_SCRIPT_SET(
// Connect to primary
HRNPQ_MACRO_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_93, TEST_PATH "/pg1", false, NULL, NULL),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_93, TEST_PATH "/pg1", false, NULL, NULL));
TEST_RESULT_VOID(
dbFree(
@ -2039,24 +2027,20 @@ testRun(void)
hrnCfgArgRawZ(argList, cfgOptRepoRetentionFull, "1");
HRN_CFG_LOAD(cfgCmdBackup, argList);
harnessPqScriptSet((HarnessPq [])
{
HRN_PQ_SCRIPT_SET(
// Connect to primary
HRNPQ_MACRO_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_93, TEST_PATH "/pg1", false, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_93, TEST_PATH "/pg1", false, NULL, NULL),
// Advance the time slowly to force retries
HRNPQ_MACRO_TIME_QUERY(1, 1575392588998),
HRNPQ_MACRO_TIME_QUERY(1, 1575392588999),
HRNPQ_MACRO_TIME_QUERY(1, 1575392589001),
HRN_PQ_SCRIPT_TIME_QUERY(1, 1575392588998),
HRN_PQ_SCRIPT_TIME_QUERY(1, 1575392588999),
HRN_PQ_SCRIPT_TIME_QUERY(1, 1575392589001),
// Stall time to force an error
HRNPQ_MACRO_TIME_QUERY(1, 1575392589998),
HRNPQ_MACRO_TIME_QUERY(1, 1575392589997),
HRNPQ_MACRO_TIME_QUERY(1, 1575392589998),
HRNPQ_MACRO_TIME_QUERY(1, 1575392589999),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_TIME_QUERY(1, 1575392589998),
HRN_PQ_SCRIPT_TIME_QUERY(1, 1575392589997),
HRN_PQ_SCRIPT_TIME_QUERY(1, 1575392589998),
HRN_PQ_SCRIPT_TIME_QUERY(1, 1575392589999));
BackupData *backupData = backupInit(
infoBackupNew(PG_VERSION_93, HRN_PG_SYSTEMID_93, hrnPgCatalogVersion(PG_VERSION_93), NULL));
@ -3076,7 +3060,8 @@ testRun(void)
// Run backup but error on first archive check
hrnBackupPqScriptP(
PG_VERSION_96, backupTimeStart, .noPriorWal = true, .backupStandby = true, .walCompressType = compressTypeGz);
PG_VERSION_96, backupTimeStart, .noPriorWal = true, .backupStandby = true, .walCompressType = compressTypeGz,
.startFast = true);
TEST_ERROR(
hrnCmdBackup(), ArchiveTimeoutError,
"WAL segment 0000000105DA69BF000000FF was not archived before the 100ms timeout\n"
@ -3086,7 +3071,8 @@ testRun(void)
// Run backup but error on archive check
hrnBackupPqScriptP(
PG_VERSION_96, backupTimeStart, .noWal = true, .backupStandby = true, .walCompressType = compressTypeGz);
PG_VERSION_96, backupTimeStart, .noWal = true, .backupStandby = true, .walCompressType = compressTypeGz,
.startFast = true);
TEST_ERROR(
hrnCmdBackup(), ArchiveTimeoutError,
"WAL segment 0000000105DA69C000000000 was not archived before the 100ms timeout\n"
@ -3106,7 +3092,8 @@ testRun(void)
const String *archiveInfoContent = strNewBuf(storageGetP(storageNewReadP(storageRepo(), INFO_ARCHIVE_PATH_FILE_STR)));
// Run backup
hrnBackupPqScriptP(PG_VERSION_96, backupTimeStart, .backupStandby = true, .walCompressType = compressTypeGz);
hrnBackupPqScriptP(
PG_VERSION_96, backupTimeStart, .backupStandby = true, .walCompressType = compressTypeGz, .startFast = true);
TEST_RESULT_VOID(hrnCmdBackup(), "backup");
// Check archive.info/copy timestamp was updated but contents were not
@ -3281,7 +3268,9 @@ testRun(void)
((Storage *)storageRepoWrite())->pub.interface.feature ^= 1 << storageFeatureHardLink;
// Run backup
hrnBackupPqScriptP(PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeGz, .walTotal = 3);
hrnBackupPqScriptP(
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeGz, .walTotal = 3, .walSwitch = true,
.tablespace = true);
TEST_RESULT_VOID(hrnCmdBackup(), "backup");
// Reset storage features
@ -3407,7 +3396,7 @@ testRun(void)
HRN_CFG_LOAD(cfgCmdBackup, argList);
// Preserve prior timestamp on pg_control
hrnBackupPqScriptP(PG_VERSION_11, BACKUP_EPOCH + 2300000, .errorAfterStart = true);
hrnBackupPqScriptP(PG_VERSION_11, BACKUP_EPOCH + 2300000, .errorAfterStart = true, .tablespace = true);
HRN_PG_CONTROL_TIME(storagePg(), backupTimeStart);
// Run backup
@ -3467,7 +3456,8 @@ testRun(void)
const char *rel1_3Sha1 = strZ(strNewEncode(encodingHex, cryptoHashOne(hashTypeSha1, relation)));
// Run backup. Make sure that the timeline selected converts to hexdecimal that can't be interpreted as decimal.
hrnBackupPqScriptP(PG_VERSION_11, backupTimeStart, .timeline = 0x2C, .walTotal = 2);
hrnBackupPqScriptP(
PG_VERSION_11, backupTimeStart, .timeline = 0x2C, .walTotal = 2, .walSwitch = true, .tablespace = true);
TEST_RESULT_VOID(hrnCmdBackup(), "backup");
TEST_RESULT_LOG(
@ -3617,7 +3607,8 @@ testRun(void)
// Run backup
hrnBackupPqScriptP(
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeGz, .walTotal = 2, .pgVersionForce = STRDEF("11"));
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeGz, .walTotal = 2, .pgVersionForce = STRDEF("11"),
.walSwitch = true, .tablespace = true);
TEST_RESULT_VOID(hrnCmdBackup(), "backup");
TEST_RESULT_LOG(
@ -3747,7 +3738,9 @@ testRun(void)
HRN_STORAGE_PUT_EMPTY(storagePgWrite(), "zero", .timeModified = backupTimeStart);
// Run backup
hrnBackupPqScriptP(PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeGz, .walTotal = 2);
hrnBackupPqScriptP(
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeGz, .walTotal = 2, .walSwitch = true,
.tablespace = true);
TEST_RESULT_VOID(hrnCmdBackup(), "backup");
TEST_RESULT_LOG(
@ -3858,7 +3851,9 @@ testRun(void)
HRN_STORAGE_PUT(storagePgWrite(), "grow-to-block-incr", file, .timeModified = backupTimeStart);
// Run backup
hrnBackupPqScriptP(PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeGz, .walTotal = 2);
hrnBackupPqScriptP(
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeGz, .walTotal = 2, .walSwitch = true,
.tablespace = true);
TEST_RESULT_VOID(hrnCmdBackup(), "backup");
TEST_RESULT_LOG(
@ -3969,7 +3964,9 @@ testRun(void)
HRN_STORAGE_PUT(storagePgWrite(), "grow-to-block-incr", file, .timeModified = backupTimeStart);
// Run backup
hrnBackupPqScriptP(PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeGz, .walTotal = 2);
hrnBackupPqScriptP(
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeGz, .walTotal = 2, .walSwitch = true,
.tablespace = true);
TEST_RESULT_VOID(hrnCmdBackup(), "backup");
TEST_RESULT_LOG(
@ -4093,7 +4090,7 @@ testRun(void)
// Run backup
hrnBackupPqScriptP(
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherType = cipherTypeAes256Cbc,
.cipherPass = TEST_CIPHER_PASS, .walTotal = 2);
.cipherPass = TEST_CIPHER_PASS, .walTotal = 2, .walSwitch = true, .tablespace = true);
TEST_RESULT_VOID(hrnCmdBackup(), "backup");
TEST_RESULT_LOG(
@ -4201,7 +4198,7 @@ testRun(void)
// Run backup
hrnBackupPqScriptP(
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherType = cipherTypeAes256Cbc,
.cipherPass = TEST_CIPHER_PASS, .walTotal = 2);
.cipherPass = TEST_CIPHER_PASS, .walTotal = 2, .walSwitch = true, .tablespace = true);
TEST_RESULT_VOID(hrnCmdBackup(), "backup");
TEST_RESULT_LOG(

View File

@ -26,7 +26,7 @@ testRun(void)
const Storage *const storageTest = storagePosixNewP(TEST_PATH_STR, .write = true);
// PQfinish() is strictly checked
harnessPqScriptStrictSet(true);
hrnPqScriptStrictSet(true);
StringList *argList = strLstNew();
@ -221,14 +221,11 @@ testRun(void)
TEST_TITLE("fail to connect to database");
// Set up harness to expect a failure to connect to the database
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_CONNECTDB, .param = "[\"dbname='postgres' port=5432\"]"},
{.function = HRNPQ_STATUS, .resultInt = CONNECTION_BAD},
{.function = HRNPQ_ERRORMESSAGE, .resultZ = "error"},
{.function = HRNPQ_FINISH},
{.function = NULL}
});
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_CONNECTDB, .param = "[\"dbname='postgres' port=5432\"]"},
{.function = HRN_PQ_STATUS, .resultInt = CONNECTION_BAD},
{.function = HRN_PQ_ERRORMESSAGE, .resultZ = "error"},
{.function = HRN_PQ_FINISH});
TEST_ERROR(cmdCheck(), ConfigError, "no database found\nHINT: check indexed pg-path/pg-host configurations");
TEST_RESULT_LOG(
@ -239,12 +236,9 @@ testRun(void)
HRN_PG_CONTROL_PUT(storagePgWrite(), PG_VERSION_96);
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_96, TEST_PATH "/pg", true, NULL, NULL),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_96, TEST_PATH "/pg", true, NULL, NULL),
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ERROR(cmdCheck(), ConfigError, "primary database not found\nHINT: check indexed pg-path/pg-host configurations");
@ -264,16 +258,12 @@ testRun(void)
HRN_PG_CONTROL_PUT(storagePgIdxWrite(1), PG_VERSION_96);
// Two standbys found but no primary
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_93, "/pgdata", true, NULL, NULL),
HRNPQ_MACRO_OPEN_GE_93(8, "dbname='postgres' port=5433", PG_VERSION_93, "/pgdata", true, NULL, NULL),
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_93, "/pgdata", true, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_93(8, "dbname='postgres' port=5433", PG_VERSION_93, "/pgdata", true, NULL, NULL),
HRNPQ_MACRO_CLOSE(8),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(8),
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ERROR(cmdCheck(), ConfigError, "primary database not found\nHINT: check indexed pg-path/pg-host configurations");
@ -288,12 +278,9 @@ testRun(void)
hrnCfgArgRawZ(argList, cfgOptArchiveTimeout, ".5");
HRN_CFG_LOAD(cfgCmdCheck, argList);
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_96, "/pgdata", true, NULL, NULL),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_96, "/pgdata", true, NULL, NULL),
HRN_PQ_SCRIPT_CLOSE(1));
// Only confirming we get passed the check for repoIsLocal || more than one pg-path configured
TEST_ERROR(
@ -314,12 +301,9 @@ testRun(void)
HRN_CFG_LOAD(cfgCmdCheck, argList);
// Primary database connection ok
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_96, TEST_PATH "/pg", false, NULL, NULL),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_96, TEST_PATH "/pg", false, NULL, NULL),
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ERROR(
cmdCheck(), FileMissingError,
@ -351,16 +335,12 @@ testRun(void)
HRN_PG_CONTROL_PUT(storagePgWrite(), PG_VERSION_15);
// Standby database path doesn't match pg_control
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_15, TEST_PATH, true, NULL, NULL),
HRNPQ_MACRO_OPEN_GE_96(8, "dbname='postgres' port=5433", PG_VERSION_15, TEST_PATH "/pg8", false, NULL, NULL),
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_15, TEST_PATH, true, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_96(8, "dbname='postgres' port=5433", PG_VERSION_15, TEST_PATH "/pg8", false, NULL, NULL),
HRNPQ_MACRO_CLOSE(8),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(8),
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ERROR(
cmdCheck(), DbMismatchError,
@ -398,16 +378,12 @@ testRun(void)
",\"db-version\":\"15\"}\n");
// Single repo config - error when checking archive mode setting on database
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_15, TEST_PATH "/pg", true, NULL, NULL),
HRNPQ_MACRO_OPEN_GE_96(8, "dbname='postgres' port=5433", PG_VERSION_15, TEST_PATH "/pg8", false, "off", NULL),
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_15, TEST_PATH "/pg", true, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_96(8, "dbname='postgres' port=5433", PG_VERSION_15, TEST_PATH "/pg8", false, "off", NULL),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_CLOSE(8),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(1),
HRN_PQ_SCRIPT_CLOSE(8));
// Error on primary but standby check ok
TEST_ERROR(cmdCheck(), ArchiveDisabledError, "archive_mode must be enabled");
@ -423,16 +399,12 @@ testRun(void)
hrnCfgArgKeyRawZ(argListRepo2, cfgOptRepoPath, 2, TEST_PATH "/repo2");
HRN_CFG_LOAD(cfgCmdCheck, argListRepo2);
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_15, TEST_PATH "/pg", true, NULL, NULL),
HRNPQ_MACRO_OPEN_GE_96(8, "dbname='postgres' port=5433", PG_VERSION_15, TEST_PATH "/pg8", false, NULL, NULL),
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_15, TEST_PATH "/pg", true, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_96(8, "dbname='postgres' port=5433", PG_VERSION_15, TEST_PATH "/pg8", false, NULL, NULL),
HRNPQ_MACRO_CLOSE(8),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(8),
HRN_PQ_SCRIPT_CLOSE(1));
// Stanza has not yet been created on repo2 but is created (and checked) on repo1
TEST_ERROR_FMT(
@ -489,14 +461,11 @@ testRun(void)
",\"db-version\":\"15\"}\n");
// Error when WAL segment not found
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_15, TEST_PATH "/pg", false, NULL, NULL),
HRNPQ_MACRO_CREATE_RESTORE_POINT(1, "1/1"),
HRNPQ_MACRO_WAL_SWITCH(1, "wal", "000000010000000100000001"),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_15, TEST_PATH "/pg", false, NULL, NULL),
HRN_PQ_SCRIPT_CREATE_RESTORE_POINT(1, "1/1"),
HRN_PQ_SCRIPT_WAL_SWITCH(1, "wal", "000000010000000100000001"),
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ERROR(
cmdCheck(), ArchiveTimeoutError,
@ -540,14 +509,11 @@ testRun(void)
bufUsedSet(buffer, bufSize(buffer));
// WAL segment switch is performed once for all repos
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_15, TEST_PATH "/pg", false, NULL, NULL),
HRNPQ_MACRO_CREATE_RESTORE_POINT(1, "1/1"),
HRNPQ_MACRO_WAL_SWITCH(1, "wal", "000000010000000100000001"),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_15, TEST_PATH "/pg", false, NULL, NULL),
HRN_PQ_SCRIPT_CREATE_RESTORE_POINT(1, "1/1"),
HRN_PQ_SCRIPT_WAL_SWITCH(1, "wal", "000000010000000100000001"),
HRN_PQ_SCRIPT_CLOSE(1));
HRN_STORAGE_PUT(
storageRepoIdxWrite(0), STORAGE_REPO_ARCHIVE "/15-1/000000010000000100000001-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
@ -609,15 +575,12 @@ testRun(void)
DbGetResult db = {0};
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_11, TEST_PATH "/pg", false, NULL, NULL),
HRNPQ_MACRO_OPEN_GE_96(8, "dbname='postgres' port=5433", PG_VERSION_11, "/badpath", true, NULL, NULL),
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_11, TEST_PATH "/pg", false, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_96(8, "dbname='postgres' port=5433", PG_VERSION_11, "/badpath", true, NULL, NULL),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_CLOSE(8),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(1),
HRN_PQ_SCRIPT_CLOSE(8));
TEST_ASSIGN(db, dbGet(false, false, false), "get primary and standby");
@ -676,12 +639,9 @@ testRun(void)
hrnCfgArgRawZ(argList, cfgOptRepoPath, TEST_PATH "/repo");
HRN_CFG_LOAD(cfgCmdCheck, argList);
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_11, TEST_PATH "/pg", false, "always", NULL),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_11, TEST_PATH "/pg", false, "always", NULL),
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ASSIGN(db, dbGet(true, true, false), "get primary");
TEST_ERROR(

View File

@ -565,11 +565,8 @@ testRun(void)
// Create pg_control
HRN_PG_CONTROL_PUT(storagePgWrite(), PG_VERSION_93);
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_93, TEST_PATH "/pg", false, NULL, NULL),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_93, TEST_PATH "/pg", false, NULL, NULL));
TEST_RESULT_VOID(cmdStanzaCreate(), "stanza create - db online");
TEST_RESULT_LOG("P00 INFO: stanza-create for stanza 'db' on repo1");
@ -586,11 +583,8 @@ testRun(void)
.comment = "stanza created");
HRN_CFG_LOAD(cfgCmdStanzaUpgrade, argList);
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_93, TEST_PATH "/pg", false, NULL, NULL),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_93, TEST_PATH "/pg", false, NULL, NULL));
TEST_RESULT_VOID(cmdStanzaUpgrade(), "stanza upgrade - db online");
TEST_RESULT_LOG(
@ -603,11 +597,8 @@ testRun(void)
// Create pg_control with different version
HRN_PG_CONTROL_PUT(storagePgWrite(), PG_VERSION_10);
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_11, TEST_PATH "/pg", false, NULL, NULL),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_11, TEST_PATH "/pg", false, NULL, NULL));
TEST_ERROR(
pgValidate(), DbMismatchError,
@ -621,11 +612,8 @@ testRun(void)
// Create pg_control
HRN_PG_CONTROL_PUT(storagePgWrite(), PG_VERSION_15);
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_15, TEST_PATH "/pg2", false, NULL, NULL),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_15, TEST_PATH "/pg2", false, NULL, NULL));
TEST_ERROR(
pgValidate(), DbMismatchError,
@ -651,12 +639,9 @@ testRun(void)
// Create pg_control for standby
HRN_PG_CONTROL_PUT(storagePgIdxWrite(0), PG_VERSION_94);
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_13, TEST_PATH "/pg", true, NULL, NULL),
HRNPQ_MACRO_OPEN_GE_96(2, "dbname='postgres' port=5434", PG_VERSION_13, TEST_PATH "/pg1", false, NULL, NULL),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_13, TEST_PATH "/pg", true, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_96(2, "dbname='postgres' port=5434", PG_VERSION_13, TEST_PATH "/pg1", false, NULL, NULL));
PgControl pgControl = {0};
TEST_ASSIGN(pgControl, pgValidate(), "validate primary on pg2");

View File

@ -17,36 +17,36 @@ Test Database
Macro to check that replay is making progress -- this does not seem useful enough to be included in the pq harness header
***********************************************************************************************************************************/
#define \
HRNPQ_MACRO_REPLAY_TARGET_REACHED_PROGRESS( \
HRN_PQ_SCRIPT_REPLAY_TARGET_REACHED_PROGRESS( \
sessionParam, walNameParam, lsnNameParam, targetLsnParam, targetReachedParam, replayLsnParam, replayLastLsnParam, \
replayProgressParam, sleepParam) \
{.session = sessionParam, \
.function = HRNPQ_SENDQUERY, \
.function = HRN_PQ_SENDQUERY, \
.param = \
"[\"select replayLsn::text,\\n" \
" (replayLsn > '" targetLsnParam "')::bool as targetReached,\\n" \
" (replayLsn > '" replayLastLsnParam "')::bool as replayProgress\\n" \
" from pg_catalog.pg_last_" walNameParam "_replay_" lsnNameParam "() as replayLsn\"]", \
.resultInt = 1, .sleep = sleepParam}, \
{.session = sessionParam, .function = HRNPQ_CONSUMEINPUT}, \
{.session = sessionParam, .function = HRNPQ_ISBUSY}, \
{.session = sessionParam, .function = HRNPQ_GETRESULT}, \
{.session = sessionParam, .function = HRNPQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK}, \
{.session = sessionParam, .function = HRNPQ_NTUPLES, .resultInt = 1}, \
{.session = sessionParam, .function = HRNPQ_NFIELDS, .resultInt = 3}, \
{.session = sessionParam, .function = HRNPQ_FTYPE, .param = "[0]", .resultInt = HRNPQ_TYPE_TEXT}, \
{.session = sessionParam, .function = HRNPQ_FTYPE, .param = "[1]", .resultInt = HRNPQ_TYPE_BOOL}, \
{.session = sessionParam, .function = HRNPQ_FTYPE, .param = "[2]", .resultInt = HRNPQ_TYPE_BOOL}, \
{.session = sessionParam, .function = HRNPQ_GETVALUE, .param = "[0,0]", .resultZ = replayLsnParam}, \
{.session = sessionParam, .function = HRNPQ_GETVALUE, .param = "[0,1]", .resultZ = cvtBoolToConstZ(targetReachedParam)}, \
{.session = sessionParam, .function = HRNPQ_GETVALUE, .param = "[0,2]", .resultZ = cvtBoolToConstZ(replayProgressParam)}, \
{.session = sessionParam, .function = HRNPQ_CLEAR}, \
{.session = sessionParam, .function = HRNPQ_GETRESULT, .resultNull = true}
{.session = sessionParam, .function = HRN_PQ_CONSUMEINPUT}, \
{.session = sessionParam, .function = HRN_PQ_ISBUSY}, \
{.session = sessionParam, .function = HRN_PQ_GETRESULT}, \
{.session = sessionParam, .function = HRN_PQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK}, \
{.session = sessionParam, .function = HRN_PQ_NTUPLES, .resultInt = 1}, \
{.session = sessionParam, .function = HRN_PQ_NFIELDS, .resultInt = 3}, \
{.session = sessionParam, .function = HRN_PQ_FTYPE, .param = "[0]", .resultInt = HRN_PQ_TYPE_TEXT}, \
{.session = sessionParam, .function = HRN_PQ_FTYPE, .param = "[1]", .resultInt = HRN_PQ_TYPE_BOOL}, \
{.session = sessionParam, .function = HRN_PQ_FTYPE, .param = "[2]", .resultInt = HRN_PQ_TYPE_BOOL}, \
{.session = sessionParam, .function = HRN_PQ_GETVALUE, .param = "[0,0]", .resultZ = replayLsnParam}, \
{.session = sessionParam, .function = HRN_PQ_GETVALUE, .param = "[0,1]", .resultZ = cvtBoolToConstZ(targetReachedParam)}, \
{.session = sessionParam, .function = HRN_PQ_GETVALUE, .param = "[0,2]", .resultZ = cvtBoolToConstZ(replayProgressParam)}, \
{.session = sessionParam, .function = HRN_PQ_CLEAR}, \
{.session = sessionParam, .function = HRN_PQ_GETRESULT, .resultNull = true}
#define \
HRNPQ_MACRO_REPLAY_TARGET_REACHED_PROGRESS_GE_10( \
HRN_PQ_SCRIPT_REPLAY_TARGET_REACHED_PROGRESS_GE_10( \
sessionParam, targetLsnParam, targetReachedParam, replayLsnParam, replayLastLsnParam, replayProgressParam, sleepParam) \
HRNPQ_MACRO_REPLAY_TARGET_REACHED_PROGRESS( \
HRN_PQ_SCRIPT_REPLAY_TARGET_REACHED_PROGRESS( \
sessionParam, "wal", "lsn", targetLsnParam, targetReachedParam, replayLsnParam, replayLastLsnParam, replayProgressParam, \
sleepParam)
@ -59,7 +59,7 @@ testRun(void)
FUNCTION_HARNESS_VOID();
// PQfinish() is strictly checked
harnessPqScriptStrictSet(true);
hrnPqScriptStrictSet(true);
// *****************************************************************************************************************************
if (testBegin("Db and dbProtocol()"))
@ -79,28 +79,24 @@ testRun(void)
HRN_CFG_LOAD(cfgCmdBackup, argList, .role = cfgCmdRoleRemote);
// Set script
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN(1, "dbname='testdb' port=5432"),
HRNPQ_MACRO_SET_SEARCH_PATH(1),
HRNPQ_MACRO_SET_CLIENT_ENCODING(1),
HRNPQ_MACRO_VALIDATE_QUERY(1, PG_VERSION_93, TEST_PATH "/pg", NULL, NULL),
HRNPQ_MACRO_SET_APPLICATION_NAME(1),
HRNPQ_MACRO_IS_STANDBY_QUERY(1, false),
HRNPQ_MACRO_CLOSE(1),
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN(1, "dbname='testdb' port=5432"),
HRN_PQ_SCRIPT_SET_SEARCH_PATH(1),
HRN_PQ_SCRIPT_SET_CLIENT_ENCODING(1),
HRN_PQ_SCRIPT_VALIDATE_QUERY(1, PG_VERSION_93, TEST_PATH "/pg", NULL, NULL),
HRN_PQ_SCRIPT_SET_APPLICATION_NAME(1),
HRN_PQ_SCRIPT_IS_STANDBY_QUERY(1, false),
HRN_PQ_SCRIPT_CLOSE(1),
HRNPQ_MACRO_OPEN(1, "dbname='testdb' port=5432"),
HRNPQ_MACRO_SET_SEARCH_PATH(1),
HRNPQ_MACRO_SET_CLIENT_ENCODING(1),
HRNPQ_MACRO_VALIDATE_QUERY(1, PG_VERSION_93, TEST_PATH "/pg", NULL, NULL),
HRNPQ_MACRO_SET_APPLICATION_NAME(1),
HRNPQ_MACRO_IS_STANDBY_QUERY(1, false),
HRNPQ_MACRO_CREATE_RESTORE_POINT(1, "2/3"),
HRNPQ_MACRO_WAL_SWITCH(1, "xlog", "000000030000000200000003"),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_OPEN(1, "dbname='testdb' port=5432"),
HRN_PQ_SCRIPT_SET_SEARCH_PATH(1),
HRN_PQ_SCRIPT_SET_CLIENT_ENCODING(1),
HRN_PQ_SCRIPT_VALIDATE_QUERY(1, PG_VERSION_93, TEST_PATH "/pg", NULL, NULL),
HRN_PQ_SCRIPT_SET_APPLICATION_NAME(1),
HRN_PQ_SCRIPT_IS_STANDBY_QUERY(1, false),
HRN_PQ_SCRIPT_CREATE_RESTORE_POINT(1, "2/3"),
HRN_PQ_SCRIPT_WAL_SWITCH(1, "xlog", "000000030000000200000003"),
HRN_PQ_SCRIPT_CLOSE(1));
// Create server
ProtocolServer *server = NULL;
@ -215,50 +211,43 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("error when unable to select any pg_settings");
harnessPqScriptSet((HarnessPq [])
{
HRN_PQ_SCRIPT_SET(
// Connect to primary
HRNPQ_MACRO_OPEN(1, "dbname='backupdb' port=5432"),
HRNPQ_MACRO_SET_SEARCH_PATH(1),
HRNPQ_MACRO_SET_CLIENT_ENCODING(1),
HRN_PQ_SCRIPT_OPEN(1, "dbname='backupdb' port=5432"),
HRN_PQ_SCRIPT_SET_SEARCH_PATH(1),
HRN_PQ_SCRIPT_SET_CLIENT_ENCODING(1),
// Return NULL for a row in pg_settings
{
.session = 1,
.function = HRNPQ_SENDQUERY,
.param =
"[\"select (select setting from pg_catalog.pg_settings where name = 'server_version_num')::int4,"
" (select setting from pg_catalog.pg_settings where name = 'data_directory')::text,"
" (select setting from pg_catalog.pg_settings where name = 'archive_mode')::text,"
" (select setting from pg_catalog.pg_settings where name = 'archive_command')::text,"
" (select setting from pg_catalog.pg_settings where name = 'checkpoint_timeout')::int4\"]",
.resultInt = 1,
},
{.session = 1, .function = HRNPQ_CONSUMEINPUT},
{.session = 1, .function = HRNPQ_ISBUSY},
{.session = 1, .function = HRNPQ_GETRESULT},
{.session = 1, .function = HRNPQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
{.session = 1, .function = HRNPQ_NTUPLES, .resultInt = 1},
{.session = 1, .function = HRNPQ_NFIELDS, .resultInt = 5},
{.session = 1, .function = HRNPQ_FTYPE, .param = "[0]", .resultInt = HRNPQ_TYPE_INT4},
{.session = 1, .function = HRNPQ_FTYPE, .param = "[1]", .resultInt = HRNPQ_TYPE_TEXT},
{.session = 1, .function = HRNPQ_FTYPE, .param = "[2]", .resultInt = HRNPQ_TYPE_TEXT},
{.session = 1, .function = HRNPQ_FTYPE, .param = "[3]", .resultInt = HRNPQ_TYPE_TEXT},
{.session = 1, .function = HRNPQ_FTYPE, .param = "[4]", .resultInt = HRNPQ_TYPE_INT4},
{.session = 1, .function = HRNPQ_GETVALUE, .param = "[0,0]", .resultZ = "0"},
{.session = 1, .function = HRNPQ_GETVALUE, .param = "[0,1]", .resultZ = "value"},
{.session = 1, .function = HRNPQ_GETVALUE, .param = "[0,2]", .resultZ = "value"},
{.session = 1, .function = HRNPQ_GETVALUE, .param = "[0,3]", .resultZ = ""},
{.session = 1, .function = HRNPQ_GETISNULL, .param = "[0,3]", .resultInt = 1},
{.session = 1, .function = HRNPQ_GETVALUE, .param = "[0,4]", .resultZ = "300"},
{.session = 1, .function = HRNPQ_CLEAR},
{.session = 1, .function = HRNPQ_GETRESULT, .resultNull = true},
{.session = 1, .function = HRN_PQ_SENDQUERY,
.param =
"[\"select (select setting from pg_catalog.pg_settings where name = 'server_version_num')::int4,"
" (select setting from pg_catalog.pg_settings where name = 'data_directory')::text,"
" (select setting from pg_catalog.pg_settings where name = 'archive_mode')::text,"
" (select setting from pg_catalog.pg_settings where name = 'archive_command')::text,"
" (select setting from pg_catalog.pg_settings where name = 'checkpoint_timeout')::int4\"]",
.resultInt = 1},
{.session = 1, .function = HRN_PQ_CONSUMEINPUT},
{.session = 1, .function = HRN_PQ_ISBUSY},
{.session = 1, .function = HRN_PQ_GETRESULT},
{.session = 1, .function = HRN_PQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
{.session = 1, .function = HRN_PQ_NTUPLES, .resultInt = 1},
{.session = 1, .function = HRN_PQ_NFIELDS, .resultInt = 5},
{.session = 1, .function = HRN_PQ_FTYPE, .param = "[0]", .resultInt = HRN_PQ_TYPE_INT4},
{.session = 1, .function = HRN_PQ_FTYPE, .param = "[1]", .resultInt = HRN_PQ_TYPE_TEXT},
{.session = 1, .function = HRN_PQ_FTYPE, .param = "[2]", .resultInt = HRN_PQ_TYPE_TEXT},
{.session = 1, .function = HRN_PQ_FTYPE, .param = "[3]", .resultInt = HRN_PQ_TYPE_TEXT},
{.session = 1, .function = HRN_PQ_FTYPE, .param = "[4]", .resultInt = HRN_PQ_TYPE_INT4},
{.session = 1, .function = HRN_PQ_GETVALUE, .param = "[0,0]", .resultZ = "0"},
{.session = 1, .function = HRN_PQ_GETVALUE, .param = "[0,1]", .resultZ = "value"},
{.session = 1, .function = HRN_PQ_GETVALUE, .param = "[0,2]", .resultZ = "value"},
{.session = 1, .function = HRN_PQ_GETVALUE, .param = "[0,3]", .resultZ = ""},
{.session = 1, .function = HRN_PQ_GETISNULL, .param = "[0,3]", .resultInt = 1},
{.session = 1, .function = HRN_PQ_GETVALUE, .param = "[0,4]", .resultZ = "300"},
{.session = 1, .function = HRN_PQ_CLEAR},
{.session = 1, .function = HRN_PQ_GETRESULT, .resultNull = true},
// Close primary
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ERROR(
dbGet(true, true, false), DbConnectError,
@ -275,32 +264,28 @@ testRun(void)
HRN_PG_CONTROL_PUT(storagePgIdxWrite(0), PG_VERSION_93, .checkpoint = pgLsnFromStr(STRDEF("2/3")));
harnessPqScriptSet((HarnessPq [])
{
HRN_PQ_SCRIPT_SET(
// Connect to primary
HRNPQ_MACRO_OPEN_GE_93(1, "dbname='backupdb' port=5432", PG_VERSION_95, TEST_PATH "/pg1", false, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_93(1, "dbname='backupdb' port=5432", PG_VERSION_95, TEST_PATH "/pg1", false, NULL, NULL),
// Get start time
HRNPQ_MACRO_TIME_QUERY(1, 1000),
HRN_PQ_SCRIPT_TIME_QUERY(1, 1000),
// Start backup errors on advisory lock
HRNPQ_MACRO_ADVISORY_LOCK(1, false),
HRN_PQ_SCRIPT_ADVISORY_LOCK(1, false),
// Start backup
HRNPQ_MACRO_ADVISORY_LOCK(1, true),
HRNPQ_MACRO_IS_IN_BACKUP(1, false),
HRNPQ_MACRO_START_BACKUP_LE_95(1, false, "2/3", "000000010000000200000003"),
HRNPQ_MACRO_DATABASE_LIST_1(1, "test1"),
HRNPQ_MACRO_TABLESPACE_LIST_0(1),
HRN_PQ_SCRIPT_ADVISORY_LOCK(1, true),
HRN_PQ_SCRIPT_IS_IN_BACKUP(1, false),
HRN_PQ_SCRIPT_START_BACKUP_LE_95(1, false, "2/3", "000000010000000200000003"),
HRN_PQ_SCRIPT_DATABASE_LIST_1(1, "test1"),
HRN_PQ_SCRIPT_TABLESPACE_LIST_0(1),
// Stop backup
HRNPQ_MACRO_STOP_BACKUP_LE_95(1, "2/4", "000000010000000200000004"),
HRN_PQ_SCRIPT_STOP_BACKUP_LE_95(1, "2/4", "000000010000000200000004"),
// Close primary
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(1));
DbGetResult db = {0};
TEST_ASSIGN(db, dbGet(true, true, false), "get primary");
@ -334,29 +319,25 @@ testRun(void)
HRN_PG_CONTROL_PUT(storagePgIdxWrite(0), PG_VERSION_93, .checkpoint = pgLsnFromStr(STRDEF("2/5")));
harnessPqScriptSet((HarnessPq [])
{
HRN_PQ_SCRIPT_SET(
// Connect to primary
HRNPQ_MACRO_OPEN_GE_93(1, "dbname='backupdb' port=5432", PG_VERSION_95, TEST_PATH "/pg1", false, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_93(1, "dbname='backupdb' port=5432", PG_VERSION_95, TEST_PATH "/pg1", false, NULL, NULL),
// Start backup when backup is in progress
HRNPQ_MACRO_ADVISORY_LOCK(1, true),
HRNPQ_MACRO_IS_IN_BACKUP(1, true),
HRN_PQ_SCRIPT_ADVISORY_LOCK(1, true),
HRN_PQ_SCRIPT_IS_IN_BACKUP(1, true),
// Stop old backup
HRNPQ_MACRO_STOP_BACKUP_LE_95(1, "1/1", "000000010000000100000001"),
HRN_PQ_SCRIPT_STOP_BACKUP_LE_95(1, "1/1", "000000010000000100000001"),
// Start backup
HRNPQ_MACRO_START_BACKUP_LE_95(1, true, "2/5", "000000010000000200000005"),
HRN_PQ_SCRIPT_START_BACKUP_LE_95(1, true, "2/5", "000000010000000200000005"),
// Stop backup
HRNPQ_MACRO_STOP_BACKUP_LE_95(1, "2/6", "000000010000000200000006"),
HRN_PQ_SCRIPT_STOP_BACKUP_LE_95(1, "2/6", "000000010000000200000006"),
// Close primary
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ASSIGN(db, dbGet(true, true, false), "get primary");
@ -375,34 +356,30 @@ testRun(void)
HRN_PG_CONTROL_PUT(storagePgIdxWrite(0), PG_VERSION_93, .checkpoint = pgLsnFromStr(STRDEF("3/3")));
harnessPqScriptSet((HarnessPq [])
{
HRN_PQ_SCRIPT_SET(
// Connect to primary
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='backupdb' port=5432", PG_VERSION_96, TEST_PATH "/pg1", false, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='backupdb' port=5432", PG_VERSION_96, TEST_PATH "/pg1", false, NULL, NULL),
// Start backup with timeline error
HRNPQ_MACRO_ADVISORY_LOCK(1, true),
HRNPQ_MACRO_CURRENT_WAL_LE_96(1, "000000020000000300000002"),
HRNPQ_MACRO_START_BACKUP_96(1, false, "3/3", "000000020000000300000003"),
HRN_PQ_SCRIPT_ADVISORY_LOCK(1, true),
HRN_PQ_SCRIPT_CURRENT_WAL_LE_96(1, "000000020000000300000002"),
HRN_PQ_SCRIPT_START_BACKUP_96(1, false, "3/3", "000000020000000300000003"),
// Start backup with checkpoint error
HRNPQ_MACRO_ADVISORY_LOCK(1, true),
HRNPQ_MACRO_CURRENT_WAL_LE_96(1, "000000010000000400000003"),
HRNPQ_MACRO_START_BACKUP_96(1, false, "4/4", "000000010000000400000004"),
HRN_PQ_SCRIPT_ADVISORY_LOCK(1, true),
HRN_PQ_SCRIPT_CURRENT_WAL_LE_96(1, "000000010000000400000003"),
HRN_PQ_SCRIPT_START_BACKUP_96(1, false, "4/4", "000000010000000400000004"),
// Start backup
HRNPQ_MACRO_ADVISORY_LOCK(1, true),
HRNPQ_MACRO_CURRENT_WAL_LE_96(1, "000000010000000300000002"),
HRNPQ_MACRO_START_BACKUP_96(1, false, "3/3", "000000010000000300000003"),
HRN_PQ_SCRIPT_ADVISORY_LOCK(1, true),
HRN_PQ_SCRIPT_CURRENT_WAL_LE_96(1, "000000010000000300000002"),
HRN_PQ_SCRIPT_START_BACKUP_96(1, false, "3/3", "000000010000000300000003"),
// Stop backup
HRNPQ_MACRO_STOP_BACKUP_96(1, "3/4", "000000010000000300000004", false),
HRN_PQ_SCRIPT_STOP_BACKUP_96(1, "3/4", "000000010000000300000004", false),
// Close primary
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ASSIGN(db, dbGet(true, true, false), "get primary");
@ -440,39 +417,35 @@ testRun(void)
HRN_PG_CONTROL_PUT(storagePgIdxWrite(0), PG_VERSION_93, .timeline = 5, .checkpoint = pgLsnFromStr(STRDEF("5/4")));
HRN_PG_CONTROL_PUT(storagePgIdxWrite(1), PG_VERSION_93, .timeline = 5, .checkpoint = pgLsnFromStr(STRDEF("5/4")));
harnessPqScriptSet((HarnessPq [])
{
HRN_PQ_SCRIPT_SET(
// Connect to primary
HRNPQ_MACRO_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_95, TEST_PATH "/pg1", false, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_95, TEST_PATH "/pg1", false, NULL, NULL),
// Connect to standby
HRNPQ_MACRO_OPEN_GE_93(2, "dbname='postgres' port=5433", PG_VERSION_95, TEST_PATH "/pg2", true, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_93(2, "dbname='postgres' port=5433", PG_VERSION_95, TEST_PATH "/pg2", true, NULL, NULL),
// Start backup
HRNPQ_MACRO_ADVISORY_LOCK(1, true),
HRNPQ_MACRO_START_BACKUP_LE_95(1, false, "5/4", "000000050000000500000004"),
HRN_PQ_SCRIPT_ADVISORY_LOCK(1, true),
HRN_PQ_SCRIPT_START_BACKUP_LE_95(1, false, "5/4", "000000050000000500000004"),
// Wait for standby to sync
HRNPQ_MACRO_REPLAY_WAIT_LE_95(2, "5/4"),
HRN_PQ_SCRIPT_REPLAY_WAIT_LE_95(2, "5/4"),
// Ping
HRNPQ_MACRO_IS_STANDBY_QUERY(1, true),
HRNPQ_MACRO_IS_STANDBY_QUERY(1, false),
HRNPQ_MACRO_IS_STANDBY_QUERY(1, false),
HRN_PQ_SCRIPT_IS_STANDBY_QUERY(1, true),
HRN_PQ_SCRIPT_IS_STANDBY_QUERY(1, false),
HRN_PQ_SCRIPT_IS_STANDBY_QUERY(1, false),
HRNPQ_MACRO_IS_STANDBY_QUERY(2, false),
HRNPQ_MACRO_IS_STANDBY_QUERY(2, true),
HRNPQ_MACRO_IS_STANDBY_QUERY(2, true),
HRNPQ_MACRO_IS_STANDBY_QUERY(2, true),
HRN_PQ_SCRIPT_IS_STANDBY_QUERY(2, false),
HRN_PQ_SCRIPT_IS_STANDBY_QUERY(2, true),
HRN_PQ_SCRIPT_IS_STANDBY_QUERY(2, true),
HRN_PQ_SCRIPT_IS_STANDBY_QUERY(2, true),
// Close standby
HRNPQ_MACRO_CLOSE(2),
HRN_PQ_SCRIPT_CLOSE(2),
// Close primary
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ASSIGN(db, dbGet(false, true, true), "get primary and standby");
@ -505,85 +478,78 @@ testRun(void)
HRN_PG_CONTROL_PUT(storagePgIdxWrite(0), PG_VERSION_93, .timeline = 5, .checkpoint = pgLsnFromStr(STRDEF("5/5")));
HRN_PG_CONTROL_PUT(storagePgIdxWrite(1), PG_VERSION_93, .timeline = 5, .checkpoint = pgLsnFromStr(STRDEF("5/5")));
harnessPqScriptSet((HarnessPq [])
{
HRN_PQ_SCRIPT_SET(
// Connect to primary
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_10, TEST_PATH "/pg1", false, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_10, TEST_PATH "/pg1", false, NULL, NULL),
// Connect to standby
HRNPQ_MACRO_OPEN_GE_96(2, "dbname='postgres' port=5433", PG_VERSION_10, TEST_PATH "/pg2", true, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_96(2, "dbname='postgres' port=5433", PG_VERSION_10, TEST_PATH "/pg2", true, NULL, NULL),
// Start backup
HRNPQ_MACRO_ADVISORY_LOCK(1, true),
HRNPQ_MACRO_CURRENT_WAL_GE_10(1, "000000050000000500000005"),
HRNPQ_MACRO_START_BACKUP_GE_10(1, false, "5/5", "000000050000000500000005"),
HRN_PQ_SCRIPT_ADVISORY_LOCK(1, true),
HRN_PQ_SCRIPT_CURRENT_WAL_GE_10(1, "000000050000000500000005"),
HRN_PQ_SCRIPT_START_BACKUP_GE_10(1, false, "5/5", "000000050000000500000005"),
// Switch WAL segment so it can be checked
HRNPQ_MACRO_CREATE_RESTORE_POINT(1, "5/5"),
HRNPQ_MACRO_WAL_SWITCH(1, "wal", "000000050000000500000005"),
HRN_PQ_SCRIPT_CREATE_RESTORE_POINT(1, "5/5"),
HRN_PQ_SCRIPT_WAL_SWITCH(1, "wal", "000000050000000500000005"),
// Standby returns NULL lsn
{
.session = 2,
.function = HRNPQ_SENDQUERY,
.param =
"[\"select replayLsn::text,\\n"
" (replayLsn > '5/5')::bool as targetReached\\n"
" from pg_catalog.pg_last_wal_replay_lsn() as replayLsn\"]",
.resultInt = 1,
},
{.session = 2, .function = HRNPQ_CONSUMEINPUT},
{.session = 2, .function = HRNPQ_ISBUSY},
{.session = 2, .function = HRNPQ_GETRESULT},
{.session = 2, .function = HRNPQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
{.session = 2, .function = HRNPQ_NTUPLES, .resultInt = 1},
{.session = 2, .function = HRNPQ_NFIELDS, .resultInt = 2},
{.session = 2, .function = HRNPQ_FTYPE, .param = "[0]", .resultInt = HRNPQ_TYPE_TEXT},
{.session = 2, .function = HRNPQ_FTYPE, .param = "[1]", .resultInt = HRNPQ_TYPE_BOOL},
{.session = 2, .function = HRNPQ_GETVALUE, .param = "[0,0]", .resultZ = ""},
{.session = 2, .function = HRNPQ_GETISNULL, .param = "[0,0]", .resultInt = 1},
{.session = 2, .function = HRNPQ_GETVALUE, .param = "[0,1]", .resultZ = "false"},
{.session = 2, .function = HRNPQ_CLEAR},
{.session = 2, .function = HRNPQ_GETRESULT, .resultNull = true},
{.session = 2, .function = HRN_PQ_SENDQUERY,
.param =
"[\"select replayLsn::text,\\n"
" (replayLsn > '5/5')::bool as targetReached\\n"
" from pg_catalog.pg_last_wal_replay_lsn() as replayLsn\"]",
.resultInt = 1},
{.session = 2, .function = HRN_PQ_CONSUMEINPUT},
{.session = 2, .function = HRN_PQ_ISBUSY},
{.session = 2, .function = HRN_PQ_GETRESULT},
{.session = 2, .function = HRN_PQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
{.session = 2, .function = HRN_PQ_NTUPLES, .resultInt = 1},
{.session = 2, .function = HRN_PQ_NFIELDS, .resultInt = 2},
{.session = 2, .function = HRN_PQ_FTYPE, .param = "[0]", .resultInt = HRN_PQ_TYPE_TEXT},
{.session = 2, .function = HRN_PQ_FTYPE, .param = "[1]", .resultInt = HRN_PQ_TYPE_BOOL},
{.session = 2, .function = HRN_PQ_GETVALUE, .param = "[0,0]", .resultZ = ""},
{.session = 2, .function = HRN_PQ_GETISNULL, .param = "[0,0]", .resultInt = 1},
{.session = 2, .function = HRN_PQ_GETVALUE, .param = "[0,1]", .resultZ = "false"},
{.session = 2, .function = HRN_PQ_CLEAR},
{.session = 2, .function = HRN_PQ_GETRESULT, .resultNull = true},
// Timeout waiting for sync
HRNPQ_MACRO_REPLAY_TARGET_REACHED_GE_10(2, "5/5", false, "5/3"),
HRNPQ_MACRO_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", false, "5/3", "5/3", false, 100),
HRNPQ_MACRO_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", false, "5/3", "5/3", false, 100),
HRN_PQ_SCRIPT_REPLAY_TARGET_REACHED_GE_10(2, "5/5", false, "5/3"),
HRN_PQ_SCRIPT_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", false, "5/3", "5/3", false, 100),
HRN_PQ_SCRIPT_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", false, "5/3", "5/3", false, 100),
// Checkpoint target timeout waiting for sync
HRNPQ_MACRO_REPLAY_TARGET_REACHED_GE_10(2, "5/5", true, "5/5"),
HRNPQ_MACRO_CHECKPOINT(2),
HRNPQ_MACRO_CHECKPOINT_TARGET_REACHED_GE_10(2, "5/5", false, "5/4", 100),
HRNPQ_MACRO_CHECKPOINT_TARGET_REACHED_GE_10(2, "5/5", false, "5/4", 100),
HRN_PQ_SCRIPT_REPLAY_TARGET_REACHED_GE_10(2, "5/5", true, "5/5"),
HRN_PQ_SCRIPT_CHECKPOINT(2),
HRN_PQ_SCRIPT_CHECKPOINT_TARGET_REACHED_GE_10(2, "5/5", false, "5/4", 100),
HRN_PQ_SCRIPT_CHECKPOINT_TARGET_REACHED_GE_10(2, "5/5", false, "5/4", 100),
// Wait for standby to sync
HRNPQ_MACRO_REPLAY_TARGET_REACHED_GE_10(2, "5/5", false, "5/3"),
HRNPQ_MACRO_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", false, "5/3", "5/3", false, 0),
HRNPQ_MACRO_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", false, "5/4", "5/3", true, 0),
HRNPQ_MACRO_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", true, "5/5", "5/4", true, 0),
HRNPQ_MACRO_CHECKPOINT(2),
HRNPQ_MACRO_CHECKPOINT_TARGET_REACHED_GE_10(2, "5/5", true, "X/X", 0),
HRN_PQ_SCRIPT_REPLAY_TARGET_REACHED_GE_10(2, "5/5", false, "5/3"),
HRN_PQ_SCRIPT_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", false, "5/3", "5/3", false, 0),
HRN_PQ_SCRIPT_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", false, "5/4", "5/3", true, 0),
HRN_PQ_SCRIPT_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", true, "5/5", "5/4", true, 0),
HRN_PQ_SCRIPT_CHECKPOINT(2),
HRN_PQ_SCRIPT_CHECKPOINT_TARGET_REACHED_GE_10(2, "5/5", true, "X/X", 0),
// Fail on timeline mismatch
HRNPQ_MACRO_REPLAY_TARGET_REACHED_GE_10(2, "5/5", false, "5/3"),
HRNPQ_MACRO_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", false, "5/3", "5/3", false, 0),
HRNPQ_MACRO_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", false, "5/4", "5/3", true, 0),
HRNPQ_MACRO_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", true, "5/5", "5/4", true, 0),
HRNPQ_MACRO_CHECKPOINT(2),
HRNPQ_MACRO_CHECKPOINT_TARGET_REACHED_GE_10(2, "5/5", true, "X/X", 0),
HRN_PQ_SCRIPT_REPLAY_TARGET_REACHED_GE_10(2, "5/5", false, "5/3"),
HRN_PQ_SCRIPT_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", false, "5/3", "5/3", false, 0),
HRN_PQ_SCRIPT_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", false, "5/4", "5/3", true, 0),
HRN_PQ_SCRIPT_REPLAY_TARGET_REACHED_PROGRESS_GE_10(2, "5/5", true, "5/5", "5/4", true, 0),
HRN_PQ_SCRIPT_CHECKPOINT(2),
HRN_PQ_SCRIPT_CHECKPOINT_TARGET_REACHED_GE_10(2, "5/5", true, "X/X", 0),
// Close standby
HRNPQ_MACRO_CLOSE(2),
HRN_PQ_SCRIPT_CLOSE(2),
// Stop backup
HRNPQ_MACRO_STOP_BACKUP_GE_10(1, "5/6", "000000050000000500000006", true),
HRN_PQ_SCRIPT_STOP_BACKUP_GE_10(1, "5/6", "000000050000000500000006", true),
// Close primary
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ASSIGN(db, dbGet(false, true, true), "get primary and standby");
@ -638,21 +604,17 @@ testRun(void)
hrnCfgArgRawZ(argList, cfgOptDbTimeout, "299");
HRN_CFG_LOAD(cfgCmdBackup, argList);
harnessPqScriptSet((HarnessPq [])
{
HRN_PQ_SCRIPT_SET(
// Connect to primary
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_14, TEST_PATH "/pg1", false, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_14, TEST_PATH "/pg1", false, NULL, NULL),
// Start backup
HRNPQ_MACRO_ADVISORY_LOCK(1, true),
HRNPQ_MACRO_CURRENT_WAL_GE_10(1, "000000050000000500000004"),
HRNPQ_MACRO_START_BACKUP_GE_10(1, false, "5/5", "000000050000000500000005"),
HRN_PQ_SCRIPT_ADVISORY_LOCK(1, true),
HRN_PQ_SCRIPT_CURRENT_WAL_GE_10(1, "000000050000000500000004"),
HRN_PQ_SCRIPT_START_BACKUP_GE_10(1, false, "5/5", "000000050000000500000005"),
// Close primary
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ASSIGN(db, dbGet(true, true, false), "get primary");
TEST_ASSIGN(backupStartResult, dbBackupStart(db.primary, false, false, true), "start backup");
@ -674,24 +636,20 @@ testRun(void)
hrnCfgArgKeyRawZ(argList, cfgOptPgPath, 1, TEST_PATH "/pg1");
HRN_CFG_LOAD(cfgCmdBackup, argList);
harnessPqScriptSet((HarnessPq [])
{
HRN_PQ_SCRIPT_SET(
// Connect to primary
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_15, TEST_PATH "/pg1", false, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_15, TEST_PATH "/pg1", false, NULL, NULL),
// Start backup
HRNPQ_MACRO_ADVISORY_LOCK(1, true),
HRNPQ_MACRO_CURRENT_WAL_GE_10(1, "000000060000000600000005"),
HRNPQ_MACRO_START_BACKUP_GE_15(1, false, "6/6", "000000060000000600000006"),
HRN_PQ_SCRIPT_ADVISORY_LOCK(1, true),
HRN_PQ_SCRIPT_CURRENT_WAL_GE_10(1, "000000060000000600000005"),
HRN_PQ_SCRIPT_START_BACKUP_GE_15(1, false, "6/6", "000000060000000600000006"),
// Stop backup
HRNPQ_MACRO_STOP_BACKUP_GE_15(1, "6/7", "000000060000000600000006", false),
HRN_PQ_SCRIPT_STOP_BACKUP_GE_15(1, "6/7", "000000060000000600000006", false),
// Close primary
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ASSIGN(db, dbGet(true, true, false), "get primary");
TEST_ASSIGN(backupStartResult, dbBackupStart(db.primary, false, false, true), "start backup");
@ -727,14 +685,11 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("error connecting to primary");
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_CONNECTDB, .param = "[\"dbname='postgres' port=5432 user='bob'\"]"},
{.function = HRNPQ_STATUS, .resultInt = CONNECTION_BAD},
{.function = HRNPQ_ERRORMESSAGE, .resultZ = "error"},
{.function = HRNPQ_FINISH},
{.function = NULL}
});
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_CONNECTDB, .param = "[\"dbname='postgres' port=5432 user='bob'\"]"},
{.function = HRN_PQ_STATUS, .resultInt = CONNECTION_BAD},
{.function = HRN_PQ_ERRORMESSAGE, .resultZ = "error"},
{.function = HRN_PQ_FINISH});
TEST_ERROR(
dbGet(true, true, false), DbConnectError,
@ -747,17 +702,14 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("only available cluster is a standby");
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN(1, "dbname='postgres' port=5432 user='bob'"),
HRNPQ_MACRO_SET_SEARCH_PATH(1),
HRNPQ_MACRO_SET_CLIENT_ENCODING(1),
HRNPQ_MACRO_VALIDATE_QUERY(1, PG_VERSION_94, TEST_PATH "/pg", NULL, NULL),
HRNPQ_MACRO_SET_APPLICATION_NAME(1),
HRNPQ_MACRO_IS_STANDBY_QUERY(1, true),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN(1, "dbname='postgres' port=5432 user='bob'"),
HRN_PQ_SCRIPT_SET_SEARCH_PATH(1),
HRN_PQ_SCRIPT_SET_CLIENT_ENCODING(1),
HRN_PQ_SCRIPT_VALIDATE_QUERY(1, PG_VERSION_94, TEST_PATH "/pg", NULL, NULL),
HRN_PQ_SCRIPT_SET_APPLICATION_NAME(1),
HRN_PQ_SCRIPT_IS_STANDBY_QUERY(1, true),
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ERROR(
dbGet(true, true, false), DbConnectError,
@ -767,29 +719,24 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("standby cluster required but not found");
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN(1, "dbname='postgres' port=5432 user='bob'"),
HRNPQ_MACRO_SET_SEARCH_PATH(1),
HRNPQ_MACRO_SET_CLIENT_ENCODING(1),
HRNPQ_MACRO_VALIDATE_QUERY(1, PG_VERSION_94, TEST_PATH "/pg", NULL, NULL),
HRNPQ_MACRO_SET_APPLICATION_NAME(1),
HRNPQ_MACRO_IS_STANDBY_QUERY(1, false),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN(1, "dbname='postgres' port=5432 user='bob'"),
HRN_PQ_SCRIPT_SET_SEARCH_PATH(1),
HRN_PQ_SCRIPT_SET_CLIENT_ENCODING(1),
HRN_PQ_SCRIPT_VALIDATE_QUERY(1, PG_VERSION_94, TEST_PATH "/pg", NULL, NULL),
HRN_PQ_SCRIPT_SET_APPLICATION_NAME(1),
HRN_PQ_SCRIPT_IS_STANDBY_QUERY(1, false),
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ERROR(dbGet(false, false, true), DbConnectError, "unable to find standby cluster - cannot proceed");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("primary cluster found");
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_93(1, "dbname='postgres' port=5432 user='bob'", PG_VERSION_93, TEST_PATH "/pg1", false, NULL, NULL),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_93(
1, "dbname='postgres' port=5432 user='bob'", PG_VERSION_93, TEST_PATH "/pg1", false, NULL, NULL),
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ASSIGN(result, dbGet(true, true, false), "get primary only");
@ -816,32 +763,24 @@ testRun(void)
// Create control file
HRN_PG_CONTROL_PUT(storagePgIdxWrite(1), PG_VERSION_93);
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_95, TEST_PATH "/pg1", false, NULL, NULL),
HRNPQ_MACRO_OPEN_GE_93(8, "dbname='postgres' port=5433", PG_VERSION_95, TEST_PATH "/pg8", false, NULL, NULL),
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_93(1, "dbname='postgres' port=5432", PG_VERSION_95, TEST_PATH "/pg1", false, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_93(8, "dbname='postgres' port=5433", PG_VERSION_95, TEST_PATH "/pg8", false, NULL, NULL),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_CLOSE(8),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(1),
HRN_PQ_SCRIPT_CLOSE(8));
TEST_ERROR(dbGet(true, true, false), DbConnectError, "more than one primary cluster found");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("two standbys found but no primary");
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_96, TEST_PATH "/pg1", true, NULL, NULL),
HRNPQ_MACRO_OPEN_GE_96(8, "dbname='postgres' port=5433", PG_VERSION_96, TEST_PATH "/pg8", true, NULL, NULL),
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_96, TEST_PATH "/pg1", true, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_96(8, "dbname='postgres' port=5433", PG_VERSION_96, TEST_PATH "/pg8", true, NULL, NULL),
HRNPQ_MACRO_CLOSE(8),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(8),
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ERROR(
dbGet(false, true, false), DbConnectError,
@ -851,16 +790,12 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("two standbys and primary not required");
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_10, TEST_PATH "/pg1", true, NULL, NULL),
HRNPQ_MACRO_OPEN_GE_96(8, "dbname='postgres' port=5433", PG_VERSION_10, TEST_PATH "/pg8", true, NULL, NULL),
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_10, TEST_PATH "/pg1", true, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_96(8, "dbname='postgres' port=5433", PG_VERSION_10, TEST_PATH "/pg8", true, NULL, NULL),
HRNPQ_MACRO_CLOSE(8),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(8),
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ASSIGN(result, dbGet(false, false, false), "get standbys");
@ -887,26 +822,22 @@ testRun(void)
hrnCfgArgKeyRawZ(argList, cfgOptPgPort, 8, "5434");
HRN_CFG_LOAD(cfgCmdBackup, argList);
harnessPqScriptSet((HarnessPq [])
{
HRNPQ_MACRO_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_12, TEST_PATH "/pg1", true, NULL, NULL),
HRN_PQ_SCRIPT_SET(
HRN_PQ_SCRIPT_OPEN_GE_96(1, "dbname='postgres' port=5432", PG_VERSION_12, TEST_PATH "/pg1", true, NULL, NULL),
// pg4 error
{.session = 4, .function = HRNPQ_CONNECTDB, .param = "[\"dbname='postgres' port=5433\"]"},
{.session = 4, .function = HRNPQ_STATUS, .resultInt = CONNECTION_BAD},
{.session = 4, .function = HRNPQ_ERRORMESSAGE, .resultZ = "error"},
{.session = 4, .function = HRNPQ_FINISH},
{.session = 4, .function = HRN_PQ_CONNECTDB, .param = "[\"dbname='postgres' port=5433\"]"},
{.session = 4, .function = HRN_PQ_STATUS, .resultInt = CONNECTION_BAD},
{.session = 4, .function = HRN_PQ_ERRORMESSAGE, .resultZ = "error"},
{.session = 4, .function = HRN_PQ_FINISH},
HRNPQ_MACRO_OPEN_GE_96(8, "dbname='postgres' port=5434", PG_VERSION_12, TEST_PATH "/pg8", false, NULL, NULL),
HRN_PQ_SCRIPT_OPEN_GE_96(8, "dbname='postgres' port=5434", PG_VERSION_12, TEST_PATH "/pg8", false, NULL, NULL),
HRNPQ_MACRO_CREATE_RESTORE_POINT(8, "2/3"),
HRNPQ_MACRO_WAL_SWITCH(8, "wal", "000000010000000200000003"),
HRN_PQ_SCRIPT_CREATE_RESTORE_POINT(8, "2/3"),
HRN_PQ_SCRIPT_WAL_SWITCH(8, "wal", "000000010000000200000003"),
HRNPQ_MACRO_CLOSE(8),
HRNPQ_MACRO_CLOSE(1),
HRNPQ_MACRO_DONE()
});
HRN_PQ_SCRIPT_CLOSE(8),
HRN_PQ_SCRIPT_CLOSE(1));
TEST_ASSIGN(result, dbGet(false, true, false), "get primary and standy");

View File

@ -23,7 +23,7 @@ testRun(void)
// PQfinish() is strictly checked
#ifndef HARNESS_PQ_REAL
harnessPqScriptStrictSet(true);
hrnPqScriptStrictSet(true);
#endif
// *****************************************************************************************************************************
@ -48,14 +48,11 @@ testRun(void)
"\tIs the server running locally and accepting connections on that socket?"
#ifndef HARNESS_PQ_REAL
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_CONNECTDB, .param = "[\"dbname='postg \\\\'\\\\\\\\res' port=5433\"]"},
{.function = HRNPQ_STATUS, .resultInt = CONNECTION_BAD},
{.function = HRNPQ_ERRORMESSAGE, .resultZ = TEST_PQ_ERROR},
{.function = HRNPQ_FINISH},
{.function = NULL}
});
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_CONNECTDB, .param = "[\"dbname='postg \\\\'\\\\\\\\res' port=5433\"]"},
{.function = HRN_PQ_STATUS, .resultInt = CONNECTION_BAD},
{.function = HRN_PQ_ERRORMESSAGE, .resultZ = TEST_PQ_ERROR},
{.function = HRN_PQ_FINISH});
#endif
PgClient *client = NULL;
@ -81,15 +78,12 @@ testRun(void)
#define TEST_QUERY "select bogus from pg_class"
#ifndef HARNESS_PQ_REAL
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_CONNECTDB, .param = "[\"dbname='postgres' port=5432\"]"},
{.function = HRNPQ_STATUS, .resultInt = CONNECTION_OK},
{.function = HRNPQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 0},
{.function = HRNPQ_ERRORMESSAGE, .resultZ = TEST_PQ_ERROR "\n"},
{.function = HRNPQ_FINISH},
{.function = NULL}
});
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_CONNECTDB, .param = "[\"dbname='postgres' port=5432\"]"},
{.function = HRN_PQ_STATUS, .resultInt = CONNECTION_OK},
{.function = HRN_PQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 0},
{.function = HRN_PQ_ERRORMESSAGE, .resultZ = TEST_PQ_ERROR "\n"},
{.function = HRN_PQ_FINISH});
#endif
TEST_ASSIGN(client, pgClientOpen(pgClientNew(NULL, 5432, STRDEF("postgres"), NULL, 3000)), "new client");
@ -111,15 +105,10 @@ testRun(void)
TEST_TITLE("connect");
#ifndef HARNESS_PQ_REAL
harnessPqScriptSet((HarnessPq [])
{
{
.function = HRNPQ_CONNECTDB,
.param = "[\"dbname='postgres' port=5432 user='" TEST_USER "' host='/var/run/postgresql'\"]",
},
{.function = HRNPQ_STATUS, .resultInt = CONNECTION_OK},
{.function = NULL}
});
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_CONNECTDB,
.param = "[\"dbname='postgres' port=5432 user='" TEST_USER "' host='/var/run/postgresql'\"]"},
{.function = HRN_PQ_STATUS, .resultInt = CONNECTION_OK});
#endif
TEST_ASSIGN(
@ -136,18 +125,15 @@ testRun(void)
#define TEST_QUERY "select bogus from pg_class"
#ifndef HARNESS_PQ_REAL
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRNPQ_CONSUMEINPUT},
{.function = HRNPQ_ISBUSY},
{.function = HRNPQ_GETRESULT},
{.function = HRNPQ_RESULTSTATUS, .resultInt = PGRES_FATAL_ERROR},
{.function = HRNPQ_RESULTERRORMESSAGE, .resultZ = TEST_PQ_ERROR " \n"},
{.function = HRNPQ_CLEAR},
{.function = HRNPQ_GETRESULT, .resultNull = true},
{.function = NULL}
});
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRN_PQ_CONSUMEINPUT},
{.function = HRN_PQ_ISBUSY},
{.function = HRN_PQ_GETRESULT},
{.function = HRN_PQ_RESULTSTATUS, .resultInt = PGRES_FATAL_ERROR},
{.function = HRN_PQ_RESULTERRORMESSAGE, .resultZ = TEST_PQ_ERROR " \n"},
{.function = HRN_PQ_CLEAR},
{.function = HRN_PQ_GETRESULT, .resultNull = true});
#endif
TEST_ERROR(
@ -163,19 +149,16 @@ testRun(void)
#define TEST_QUERY "select pg_sleep(3000)"
#ifndef HARNESS_PQ_REAL
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRNPQ_CONSUMEINPUT, .sleep = 600},
{.function = HRNPQ_ISBUSY, .resultInt = 1},
{.function = HRNPQ_GETCANCEL},
{.function = HRNPQ_CANCEL, .resultInt = 1},
{.function = HRNPQ_FREECANCEL},
{.function = HRNPQ_GETRESULT},
{.function = HRNPQ_CLEAR},
{.function = HRNPQ_GETRESULT, .resultNull = true},
{.function = NULL}
});
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRN_PQ_CONSUMEINPUT, .sleep = 600},
{.function = HRN_PQ_ISBUSY, .resultInt = 1},
{.function = HRN_PQ_GETCANCEL},
{.function = HRN_PQ_CANCEL, .resultInt = 1},
{.function = HRN_PQ_FREECANCEL},
{.function = HRN_PQ_GETRESULT},
{.function = HRN_PQ_CLEAR},
{.function = HRN_PQ_GETRESULT, .resultNull = true});
#endif
TEST_ERROR(
@ -191,18 +174,15 @@ testRun(void)
#define TEST_PQ_ERROR "test error"
#define TEST_QUERY "select pg_sleep(3000)"
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRNPQ_CONSUMEINPUT, .sleep = 300},
{.function = HRNPQ_ISBUSY, .resultInt = 1},
{.function = HRNPQ_CONSUMEINPUT, .sleep = 300},
{.function = HRNPQ_ISBUSY, .resultInt = 1},
{.function = HRNPQ_GETCANCEL},
{.function = HRNPQ_CANCEL, .resultInt = 0, .resultZ = TEST_PQ_ERROR},
{.function = HRNPQ_FREECANCEL},
{.function = NULL}
});
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRN_PQ_CONSUMEINPUT, .sleep = 300},
{.function = HRN_PQ_ISBUSY, .resultInt = 1},
{.function = HRN_PQ_CONSUMEINPUT, .sleep = 300},
{.function = HRN_PQ_ISBUSY, .resultInt = 1},
{.function = HRN_PQ_GETCANCEL},
{.function = HRN_PQ_CANCEL, .resultInt = 0, .resultZ = TEST_PQ_ERROR},
{.function = HRN_PQ_FREECANCEL});
TEST_ERROR(
pgClientQuery(client, STRDEF(TEST_QUERY), pgClientQueryResultColumn), DbQueryError,
@ -218,14 +198,11 @@ testRun(void)
#define TEST_QUERY "select 1"
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRNPQ_CONSUMEINPUT, .sleep = 600},
{.function = HRNPQ_ISBUSY, .resultInt = 1},
{.function = HRNPQ_GETCANCEL, .resultNull = true},
{.function = NULL}
});
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRN_PQ_CONSUMEINPUT, .sleep = 600},
{.function = HRN_PQ_ISBUSY, .resultInt = 1},
{.function = HRN_PQ_GETCANCEL, .resultNull = true});
TEST_ERROR(
pgClientQuery(client, STRDEF(TEST_QUERY), pgClientQueryResultColumn), DbQueryError,
@ -240,17 +217,14 @@ testRun(void)
#define TEST_QUERY "set client_encoding = 'UTF8'"
#ifndef HARNESS_PQ_REAL
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRNPQ_CONSUMEINPUT},
{.function = HRNPQ_ISBUSY},
{.function = HRNPQ_GETRESULT},
{.function = HRNPQ_RESULTSTATUS, .resultInt = PGRES_COMMAND_OK},
{.function = HRNPQ_CLEAR},
{.function = HRNPQ_GETRESULT, .resultNull = true},
{.function = NULL}
});
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRN_PQ_CONSUMEINPUT},
{.function = HRN_PQ_ISBUSY},
{.function = HRN_PQ_GETRESULT},
{.function = HRN_PQ_RESULTSTATUS, .resultInt = PGRES_COMMAND_OK},
{.function = HRN_PQ_CLEAR},
{.function = HRN_PQ_GETRESULT, .resultNull = true});
#endif
TEST_ERROR(
@ -265,17 +239,14 @@ testRun(void)
#define TEST_QUERY "select * from pg_class limit 1"
#ifndef HARNESS_PQ_REAL
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRNPQ_CONSUMEINPUT},
{.function = HRNPQ_ISBUSY},
{.function = HRNPQ_GETRESULT},
{.function = HRNPQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
{.function = HRNPQ_CLEAR},
{.function = HRNPQ_GETRESULT, .resultNull = true},
{.function = NULL}
});
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRN_PQ_CONSUMEINPUT},
{.function = HRN_PQ_ISBUSY},
{.function = HRN_PQ_GETRESULT},
{.function = HRN_PQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
{.function = HRN_PQ_CLEAR},
{.function = HRN_PQ_GETRESULT, .resultNull = true});
#endif
TEST_ERROR(
@ -290,17 +261,14 @@ testRun(void)
#define TEST_QUERY "set client_encoding = 'UTF8'"
#ifndef HARNESS_PQ_REAL
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRNPQ_CONSUMEINPUT},
{.function = HRNPQ_ISBUSY},
{.function = HRNPQ_GETRESULT},
{.function = HRNPQ_RESULTSTATUS, .resultInt = PGRES_COMMAND_OK},
{.function = HRNPQ_CLEAR},
{.function = HRNPQ_GETRESULT, .resultNull = true},
{.function = NULL}
});
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRN_PQ_CONSUMEINPUT},
{.function = HRN_PQ_ISBUSY},
{.function = HRN_PQ_GETRESULT},
{.function = HRN_PQ_RESULTSTATUS, .resultInt = PGRES_COMMAND_OK},
{.function = HRN_PQ_CLEAR},
{.function = HRN_PQ_GETRESULT, .resultNull = true});
#endif
TEST_RESULT_PTR(pgClientQuery(client, STRDEF(TEST_QUERY), pgClientQueryResultAny), NULL, "execute set");
@ -313,17 +281,14 @@ testRun(void)
#define TEST_QUERY "do $$ begin raise notice 'mememe'; end $$"
#ifndef HARNESS_PQ_REAL
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRNPQ_CONSUMEINPUT},
{.function = HRNPQ_ISBUSY},
{.function = HRNPQ_GETRESULT},
{.function = HRNPQ_RESULTSTATUS, .resultInt = PGRES_COMMAND_OK},
{.function = HRNPQ_CLEAR},
{.function = HRNPQ_GETRESULT, .resultNull = true},
{.function = NULL}
});
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRN_PQ_CONSUMEINPUT},
{.function = HRN_PQ_ISBUSY},
{.function = HRN_PQ_GETRESULT},
{.function = HRN_PQ_RESULTSTATUS, .resultInt = PGRES_COMMAND_OK},
{.function = HRN_PQ_CLEAR},
{.function = HRN_PQ_GETRESULT, .resultNull = true});
#endif
TEST_RESULT_PTR(pgClientQuery(client, STRDEF(TEST_QUERY), pgClientQueryResultNone), NULL, "execute do block");
@ -336,21 +301,18 @@ testRun(void)
#define TEST_QUERY "select clock_timestamp()"
#ifndef HARNESS_PQ_REAL
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRNPQ_CONSUMEINPUT},
{.function = HRNPQ_ISBUSY},
{.function = HRNPQ_GETRESULT},
{.function = HRNPQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
{.function = HRNPQ_NTUPLES, .resultInt = 1},
{.function = HRNPQ_NFIELDS, .resultInt = 1},
{.function = HRNPQ_FTYPE, .param = "[0]", .resultInt = 1184},
{.function = HRNPQ_GETVALUE, .param = "[0,0]", .resultZ = "2019-07-25 12:06:09.000282+00"},
{.function = HRNPQ_CLEAR},
{.function = HRNPQ_GETRESULT, .resultNull = true},
{.function = NULL}
});
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRN_PQ_CONSUMEINPUT},
{.function = HRN_PQ_ISBUSY},
{.function = HRN_PQ_GETRESULT},
{.function = HRN_PQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
{.function = HRN_PQ_NTUPLES, .resultInt = 1},
{.function = HRN_PQ_NFIELDS, .resultInt = 1},
{.function = HRN_PQ_FTYPE, .param = "[0]", .resultInt = 1184},
{.function = HRN_PQ_GETVALUE, .param = "[0,0]", .resultZ = "2019-07-25 12:06:09.000282+00"},
{.function = HRN_PQ_CLEAR},
{.function = HRN_PQ_GETRESULT, .resultNull = true});
#endif
TEST_ERROR(
@ -368,37 +330,34 @@ testRun(void)
" order by relname"
#ifndef HARNESS_PQ_REAL
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRNPQ_CONSUMEINPUT},
{.function = HRNPQ_ISBUSY},
{.function = HRNPQ_GETRESULT},
{.function = HRNPQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRN_PQ_CONSUMEINPUT},
{.function = HRN_PQ_ISBUSY},
{.function = HRN_PQ_GETRESULT},
{.function = HRN_PQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
{.function = HRNPQ_NTUPLES, .resultInt = 2},
{.function = HRNPQ_NFIELDS, .resultInt = 4},
{.function = HRNPQ_FTYPE, .param = "[0]", .resultInt = HRNPQ_TYPE_OID},
{.function = HRNPQ_FTYPE, .param = "[1]", .resultInt = HRNPQ_TYPE_TEXT},
{.function = HRNPQ_FTYPE, .param = "[2]", .resultInt = HRNPQ_TYPE_TEXT},
{.function = HRNPQ_FTYPE, .param = "[3]", .resultInt = HRNPQ_TYPE_BOOL},
{.function = HRN_PQ_NTUPLES, .resultInt = 2},
{.function = HRN_PQ_NFIELDS, .resultInt = 4},
{.function = HRN_PQ_FTYPE, .param = "[0]", .resultInt = HRN_PQ_TYPE_OID},
{.function = HRN_PQ_FTYPE, .param = "[1]", .resultInt = HRN_PQ_TYPE_TEXT},
{.function = HRN_PQ_FTYPE, .param = "[2]", .resultInt = HRN_PQ_TYPE_TEXT},
{.function = HRN_PQ_FTYPE, .param = "[3]", .resultInt = HRN_PQ_TYPE_BOOL},
{.function = HRNPQ_GETVALUE, .param = "[0,0]", .resultZ = "1259"},
{.function = HRNPQ_GETVALUE, .param = "[0,1]", .resultZ = ""},
{.function = HRNPQ_GETISNULL, .param = "[0,1]", .resultInt = 1},
{.function = HRNPQ_GETVALUE, .param = "[0,2]", .resultZ = "pg_class"},
{.function = HRNPQ_GETVALUE, .param = "[0,3]", .resultZ = "t"},
{.function = HRN_PQ_GETVALUE, .param = "[0,0]", .resultZ = "1259"},
{.function = HRN_PQ_GETVALUE, .param = "[0,1]", .resultZ = ""},
{.function = HRN_PQ_GETISNULL, .param = "[0,1]", .resultInt = 1},
{.function = HRN_PQ_GETVALUE, .param = "[0,2]", .resultZ = "pg_class"},
{.function = HRN_PQ_GETVALUE, .param = "[0,3]", .resultZ = "t"},
{.function = HRNPQ_GETVALUE, .param = "[1,0]", .resultZ = "1255"},
{.function = HRNPQ_GETVALUE, .param = "[1,1]", .resultZ = ""},
{.function = HRNPQ_GETISNULL, .param = "[1,1]", .resultInt = 0},
{.function = HRNPQ_GETVALUE, .param = "[1,2]", .resultZ = "pg_proc"},
{.function = HRNPQ_GETVALUE, .param = "[1,3]", .resultZ = "f"},
{.function = HRN_PQ_GETVALUE, .param = "[1,0]", .resultZ = "1255"},
{.function = HRN_PQ_GETVALUE, .param = "[1,1]", .resultZ = ""},
{.function = HRN_PQ_GETISNULL, .param = "[1,1]", .resultInt = 0},
{.function = HRN_PQ_GETVALUE, .param = "[1,2]", .resultZ = "pg_proc"},
{.function = HRN_PQ_GETVALUE, .param = "[1,3]", .resultZ = "f"},
{.function = HRNPQ_CLEAR},
{.function = HRNPQ_GETRESULT, .resultNull = true},
{.function = NULL}
});
{.function = HRN_PQ_CLEAR},
{.function = HRN_PQ_GETRESULT, .resultNull = true});
#endif
TEST_RESULT_STR_Z(
@ -414,21 +373,18 @@ testRun(void)
#define TEST_QUERY "select * from pg_class limit 2"
#ifndef HARNESS_PQ_REAL
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRNPQ_CONSUMEINPUT},
{.function = HRNPQ_ISBUSY},
{.function = HRNPQ_GETRESULT},
{.function = HRNPQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRN_PQ_CONSUMEINPUT},
{.function = HRN_PQ_ISBUSY},
{.function = HRN_PQ_GETRESULT},
{.function = HRN_PQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
{.function = HRNPQ_NTUPLES, .resultInt = 2},
{.function = HRNPQ_NFIELDS, .resultInt = 1},
{.function = HRN_PQ_NTUPLES, .resultInt = 2},
{.function = HRN_PQ_NFIELDS, .resultInt = 1},
{.function = HRNPQ_CLEAR},
{.function = HRNPQ_GETRESULT, .resultNull = true},
{.function = NULL}
});
{.function = HRN_PQ_CLEAR},
{.function = HRN_PQ_GETRESULT, .resultNull = true});
#endif
TEST_ERROR(
@ -443,26 +399,23 @@ testRun(void)
#define TEST_QUERY "select 1259::oid, -9223372036854775807::int8"
#ifndef HARNESS_PQ_REAL
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRNPQ_CONSUMEINPUT},
{.function = HRNPQ_ISBUSY},
{.function = HRNPQ_GETRESULT},
{.function = HRNPQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRN_PQ_CONSUMEINPUT},
{.function = HRN_PQ_ISBUSY},
{.function = HRN_PQ_GETRESULT},
{.function = HRN_PQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
{.function = HRNPQ_NTUPLES, .resultInt = 1},
{.function = HRNPQ_NFIELDS, .resultInt = 2},
{.function = HRNPQ_FTYPE, .param = "[0]", .resultInt = HRNPQ_TYPE_OID},
{.function = HRNPQ_FTYPE, .param = "[1]", .resultInt = HRNPQ_TYPE_INT8},
{.function = HRN_PQ_NTUPLES, .resultInt = 1},
{.function = HRN_PQ_NFIELDS, .resultInt = 2},
{.function = HRN_PQ_FTYPE, .param = "[0]", .resultInt = HRN_PQ_TYPE_OID},
{.function = HRN_PQ_FTYPE, .param = "[1]", .resultInt = HRN_PQ_TYPE_INT8},
{.function = HRNPQ_GETVALUE, .param = "[0,0]", .resultZ = "1259"},
{.function = HRNPQ_GETVALUE, .param = "[0,1]", .resultZ = "-9223372036854775807"},
{.function = HRN_PQ_GETVALUE, .param = "[0,0]", .resultZ = "1259"},
{.function = HRN_PQ_GETVALUE, .param = "[0,1]", .resultZ = "-9223372036854775807"},
{.function = HRNPQ_CLEAR},
{.function = HRNPQ_GETRESULT, .resultNull = true},
{.function = NULL}
});
{.function = HRN_PQ_CLEAR},
{.function = HRN_PQ_GETRESULT, .resultNull = true});
#endif
TEST_RESULT_STR_Z(
@ -477,21 +430,18 @@ testRun(void)
#define TEST_QUERY "select * from pg_class limit 1"
#ifndef HARNESS_PQ_REAL
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRNPQ_CONSUMEINPUT},
{.function = HRNPQ_ISBUSY},
{.function = HRNPQ_GETRESULT},
{.function = HRNPQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRN_PQ_CONSUMEINPUT},
{.function = HRN_PQ_ISBUSY},
{.function = HRN_PQ_GETRESULT},
{.function = HRN_PQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
{.function = HRNPQ_NTUPLES, .resultInt = 1},
{.function = HRNPQ_NFIELDS, .resultInt = 2},
{.function = HRN_PQ_NTUPLES, .resultInt = 1},
{.function = HRN_PQ_NFIELDS, .resultInt = 2},
{.function = HRNPQ_CLEAR},
{.function = HRNPQ_GETRESULT, .resultNull = true},
{.function = NULL}
});
{.function = HRN_PQ_CLEAR},
{.function = HRN_PQ_GETRESULT, .resultNull = true});
#endif
TEST_ERROR(
@ -506,24 +456,21 @@ testRun(void)
#define TEST_QUERY "select -2147483647::int4"
#ifndef HARNESS_PQ_REAL
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRNPQ_CONSUMEINPUT},
{.function = HRNPQ_ISBUSY},
{.function = HRNPQ_GETRESULT},
{.function = HRNPQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_SENDQUERY, .param = "[\"" TEST_QUERY "\"]", .resultInt = 1},
{.function = HRN_PQ_CONSUMEINPUT},
{.function = HRN_PQ_ISBUSY},
{.function = HRN_PQ_GETRESULT},
{.function = HRN_PQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK},
{.function = HRNPQ_NTUPLES, .resultInt = 1},
{.function = HRNPQ_NFIELDS, .resultInt = 1},
{.function = HRNPQ_FTYPE, .param = "[0]", .resultInt = HRNPQ_TYPE_INT4},
{.function = HRN_PQ_NTUPLES, .resultInt = 1},
{.function = HRN_PQ_NFIELDS, .resultInt = 1},
{.function = HRN_PQ_FTYPE, .param = "[0]", .resultInt = HRN_PQ_TYPE_INT4},
{.function = HRNPQ_GETVALUE, .param = "[0,0]", .resultZ = "-2147483647"},
{.function = HRN_PQ_GETVALUE, .param = "[0,0]", .resultZ = "-2147483647"},
{.function = HRNPQ_CLEAR},
{.function = HRNPQ_GETRESULT, .resultNull = true},
{.function = NULL}
});
{.function = HRN_PQ_CLEAR},
{.function = HRN_PQ_GETRESULT, .resultNull = true});
#endif
TEST_RESULT_STR_Z(
@ -536,12 +483,9 @@ testRun(void)
TEST_TITLE("close connection");
#ifndef HARNESS_PQ_REAL
harnessPqScriptSet((HarnessPq [])
{
{.function = HRNPQ_FINISH},
{.function = HRNPQ_GETRESULT, .resultNull = true},
{.function = NULL}
});
HRN_PQ_SCRIPT_SET(
{.function = HRN_PQ_FINISH},
{.function = HRN_PQ_GETRESULT, .resultNull = true});
#endif
TEST_RESULT_VOID(pgClientClose(client), "close client");
TEST_RESULT_VOID(pgClientClose(client), "close client again");