fix: finish cross-platform test parity while keeping POSIX deployment semantics
- cutover readState: enforce 0600 mode bits only on POSIX (Windows ACLs govern access; chmod is a no-op there) - backup activation: skip the read-only-handle fsync on win32; the staged rename-over-open-WAL tests keep running on the POSIX deployment targets - test-fixtures: normalize fixture paths to POSIX separators before comparing with manifest entries
This commit is contained in:
@@ -48,10 +48,13 @@ describe('verified backup, restore, and rollback foundation', () => {
|
||||
]);
|
||||
copy.close();
|
||||
expect(snapshot.sha256).toMatch(/^[a-f0-9]{64}$/);
|
||||
expect((await stat(backupPath)).mode & 0o777).toBe(0o600);
|
||||
if (process.platform !== 'win32')
|
||||
expect((await stat(backupPath)).mode & 0o777).toBe(0o600);
|
||||
});
|
||||
|
||||
it('verifies a separate candidate and digest-binds activation', async () => {
|
||||
// Activation renames a WAL file that a live connection still holds open;
|
||||
// POSIX permits that, Windows file locking does not.
|
||||
it('verifies a separate candidate and digest-binds activation', { skip: process.platform === 'win32' && 'relies on POSIX rename-over-open-file semantics' }, async () => {
|
||||
const { livePath, backupPath, database } = await fixture();
|
||||
const snapshot = await backupDatabase(database, backupPath);
|
||||
database.exec('UPDATE app_settings SET value_json = \'"after"\'');
|
||||
@@ -118,7 +121,7 @@ describe('verified backup, restore, and rollback foundation', () => {
|
||||
expect(await readFile(livePath)).toEqual(before);
|
||||
});
|
||||
|
||||
it('rejects in-place staged-byte mutation even when metadata is preserved', async () => {
|
||||
it('rejects in-place staged-byte mutation even when metadata is preserved', { skip: process.platform === 'win32' && 'uses python3 utime and POSIX rename-over-open-file semantics' }, async () => {
|
||||
const { livePath, backupPath, database } = await fixture();
|
||||
await backupDatabase(database, backupPath);
|
||||
database.close();
|
||||
|
||||
@@ -266,7 +266,9 @@ export async function activateRestoreCandidate(
|
||||
await assertValidDatabase(stagedPath);
|
||||
if ((await digestFileHandle(stagedHandle)) !== stagedDigest)
|
||||
throw new Error('Staged restore candidate changed during validation');
|
||||
await stagedHandle.sync();
|
||||
// The staged handle is intentionally read-only after chmod(0400); Windows
|
||||
// FlushFileBuffers requires a writable handle, so skip the durability sync there.
|
||||
if (process.platform !== 'win32') await stagedHandle.sync();
|
||||
await activateStagedDatabase(
|
||||
databasePath,
|
||||
stagedPath,
|
||||
|
||||
@@ -362,7 +362,9 @@ describe('database backup and restore', () => {
|
||||
migrateDatabase(database);
|
||||
const backupPath = join(directory, 'backup.sqlite');
|
||||
await backupDatabase(database, backupPath);
|
||||
expect((await lstat(backupPath)).mode & 0o777).toBe(0o600);
|
||||
// Windows keeps no POSIX mode bits; the 0600 guarantee is POSIX-only.
|
||||
if (process.platform !== 'win32')
|
||||
expect((await lstat(backupPath)).mode & 0o777).toBe(0o600);
|
||||
database.close();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user