CoolFace
Datasetpublic

basant307/AI_Governance_Project

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes45downloads
writeWithBackup.test.ts229 linesDownload Raw Back to utils
1/**2 * @license3 * Copyright 2025 Google LLC4 * SPDX-License-Identifier: Apache-2.05 */6 7import { describe, it, expect, beforeEach, afterEach } from 'vitest';8import * as fs from 'node:fs';9import * as path from 'node:path';10import * as os from 'node:os';11import { writeWithBackup, writeWithBackupSync } from './writeWithBackup.js';12 13describe('writeWithBackup', () => {14  let tempDir: string;15 16  beforeEach(() => {17    tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'writeWithBackup-test-'));18  });19 20  afterEach(() => {21    // Clean up temp directory22    try {23      fs.rmSync(tempDir, { recursive: true, force: true });24    } catch (_e) {25      // Ignore cleanup errors26    }27  });28 29  describe('writeWithBackupSync', () => {30    it('should write content to a new file', () => {31      const targetPath = path.join(tempDir, 'test-file.txt');32      const content = 'Hello, World!';33 34      writeWithBackupSync(targetPath, content);35 36      expect(fs.existsSync(targetPath)).toBe(true);37      expect(fs.readFileSync(targetPath, 'utf-8')).toBe(content);38    });39 40    it('should not leave a backup file behind after a successful overwrite', () => {41      const targetPath = path.join(tempDir, 'test-file.txt');42      const originalContent = 'Original content';43      const newContent = 'New content';44 45      fs.writeFileSync(targetPath, originalContent);46      writeWithBackupSync(targetPath, newContent);47 48      // Target has the new content; the .orig safety net is cleaned up on49      // success so it does not pollute the directory.50      expect(fs.readFileSync(targetPath, 'utf-8')).toBe(newContent);51      expect(fs.existsSync(`${targetPath}.orig`)).toBe(false);52    });53 54    it('should not accumulate backups across repeated writes', () => {55      const targetPath = path.join(tempDir, 'test-file.txt');56 57      fs.writeFileSync(targetPath, 'v0');58      writeWithBackupSync(targetPath, 'v1');59      writeWithBackupSync(targetPath, 'v2');60      writeWithBackupSync(targetPath, 'v3');61 62      expect(fs.readFileSync(targetPath, 'utf-8')).toBe('v3');63      // Only the target remains in the directory.64      expect(fs.readdirSync(tempDir)).toEqual(['test-file.txt']);65    });66 67    it('should clean up the backup honoring a custom suffix', () => {68      const targetPath = path.join(tempDir, 'test-file.txt');69 70      fs.writeFileSync(targetPath, 'Original');71      writeWithBackupSync(targetPath, 'New', { backupSuffix: '.bak' });72 73      expect(fs.readFileSync(targetPath, 'utf-8')).toBe('New');74      expect(fs.existsSync(`${targetPath}.bak`)).toBe(false);75      expect(fs.existsSync(`${targetPath}.orig`)).toBe(false);76    });77 78    it('should clean up temp file on failure', () => {79      const targetPath = path.join(tempDir, 'test-file.txt');80      const tempPath = `${targetPath}.tmp`;81 82      // Create a situation where rename will fail (e.g., by creating a directory at target)83      fs.mkdirSync(targetPath);84 85      expect(() => writeWithBackupSync(targetPath, 'content')).toThrow();86      expect(fs.existsSync(tempPath)).toBe(false);87    });88 89    it('should preserve original file content when write fails after backup', () => {90      const targetPath = path.join(tempDir, 'test-file.txt');91      const originalContent = 'Original content that must be preserved';92 93      // Create original file94      fs.writeFileSync(targetPath, originalContent);95 96      // Create a situation where rename will fail (by creating a directory at temp path)97      const tempPath = `${targetPath}.tmp`;98      fs.mkdirSync(tempPath);99 100      // The write should fail101      expect(() => writeWithBackupSync(targetPath, 'New content')).toThrow();102 103      // Original file should still exist with original content104      expect(fs.existsSync(targetPath)).toBe(true);105      expect(fs.statSync(targetPath).isFile()).toBe(true);106      expect(fs.readFileSync(targetPath, 'utf-8')).toBe(originalContent);107 108      // Cleanup109      fs.rmdirSync(tempPath);110    });111 112    it('should remove the backup once the target is updated', () => {113      const targetPath = path.join(tempDir, 'test-file.txt');114      const backupPath = `${targetPath}.orig`;115      const originalContent = 'Original content';116      const newContent = 'New content';117 118      fs.writeFileSync(targetPath, originalContent);119      writeWithBackupSync(targetPath, newContent);120 121      // The backup was only an in-flight safety net; it is gone on success.122      expect(fs.existsSync(backupPath)).toBe(false);123      expect(fs.readFileSync(targetPath, 'utf-8')).toBe(newContent);124    });125 126    it('should include recovery information in error message', () => {127      const targetPath = path.join(tempDir, 'test-file.txt');128 129      // Create a situation where rename will fail (directory at target)130      fs.mkdirSync(targetPath);131 132      let errorMessage = '';133      try {134        writeWithBackupSync(targetPath, 'content');135      } catch (error) {136        errorMessage = error instanceof Error ? error.message : String(error);137      }138 139      // Error message should be descriptive140      expect(errorMessage).toContain('directory');141      expect(errorMessage.length).toBeGreaterThan(10);142    });143 144    it('should handle backup failure with descriptive error', () => {145      const targetPath = path.join(tempDir, 'test-file.txt');146      const backupPath = `${targetPath}.orig`;147      const originalContent = 'Original content';148 149      // Create original file150      fs.writeFileSync(targetPath, originalContent);151 152      // Create a directory at backup path to cause backup to fail153      fs.mkdirSync(backupPath);154 155      let errorMessage = '';156      try {157        writeWithBackupSync(targetPath, 'New content');158      } catch (error) {159        errorMessage = error instanceof Error ? error.message : String(error);160      }161 162      // Error message should mention backup failure163      expect(errorMessage).toContain('backup');164 165      // Original file should still exist166      expect(fs.existsSync(targetPath)).toBe(true);167      expect(fs.readFileSync(targetPath, 'utf-8')).toBe(originalContent);168 169      // Cleanup170      fs.rmdirSync(backupPath);171    });172 173    it('should clean up temp file when backup creation fails', () => {174      const targetPath = path.join(tempDir, 'test-file.txt');175      const tempPath = `${targetPath}.tmp`;176      const backupPath = `${targetPath}.orig`;177      const originalContent = 'Original content';178 179      // Create original file180      fs.writeFileSync(targetPath, originalContent);181 182      // Create a directory at backup path to cause backup to fail183      fs.mkdirSync(backupPath);184 185      // The write should fail186      expect(() => writeWithBackupSync(targetPath, 'New content')).toThrow();187 188      // Temp file should be cleaned up189      expect(fs.existsSync(tempPath)).toBe(false);190 191      // Cleanup192      fs.rmdirSync(backupPath);193    });194  });195 196  describe('writeWithBackup (async)', () => {197    it('should write content to a new file', async () => {198      const targetPath = path.join(tempDir, 'test-file.txt');199      const content = 'Hello, World!';200 201      await writeWithBackup(targetPath, content);202 203      expect(fs.existsSync(targetPath)).toBe(true);204      expect(fs.readFileSync(targetPath, 'utf-8')).toBe(content);205    });206 207    it('should overwrite without leaving a backup behind', async () => {208      const targetPath = path.join(tempDir, 'test-file.txt');209      const originalContent = 'Original content';210      const newContent = 'New content';211 212      fs.writeFileSync(targetPath, originalContent);213      await writeWithBackup(targetPath, newContent);214 215      expect(fs.readFileSync(targetPath, 'utf-8')).toBe(newContent);216      expect(fs.existsSync(`${targetPath}.orig`)).toBe(false);217    });218 219    it('should use custom encoding', async () => {220      const targetPath = path.join(tempDir, 'test-file.txt');221      const content = 'Hello, World!';222 223      await writeWithBackup(targetPath, content, { encoding: 'utf8' });224 225      expect(fs.readFileSync(targetPath, 'utf-8')).toBe(content);226    });227  });228});229 
basant307/AI_Governance_Project · CoolFace