Path: blob/main/tests/unit/file-permissions.test.ts
12919 views
/*1* file-permissions.test.ts2*3* Copyright (C) 2020-2026 Posit Software, PBC4*/56import { unitTest } from "../test.ts";7import { withTempDir } from "../utils.ts";8import { assert, assertEquals } from "testing/asserts";9import { join } from "../../src/deno_ral/path.ts";10import { isWindows } from "../../src/deno_ral/platform.ts";11import {12ensureUserWritable,13safeModeFromFile,14} from "../../src/deno_ral/fs.ts";1516function writeFile(dir: string, name: string, content: string, mode: number): string {17const path = join(dir, name);18Deno.writeTextFileSync(path, content);19Deno.chmodSync(path, mode);20return path;21}2223unitTest(24"file-permissions - ensureUserWritable fixes read-only files",25async () => withTempDir((dir) => {26const file = writeFile(dir, "readonly.txt", "test content", 0o444);2728const modeBefore = safeModeFromFile(file);29assert(modeBefore !== undefined);30assert((modeBefore! & 0o200) === 0, "File should be read-only before fix");3132ensureUserWritable(file);3334assertEquals(safeModeFromFile(file)! & 0o777, 0o644,35"Permission bits should be 0o644 (0o444 | 0o200) — only user write bit added");36}),37{ ignore: isWindows },38);3940unitTest(41"file-permissions - ensureUserWritable leaves writable files unchanged",42async () => withTempDir((dir) => {43const file = writeFile(dir, "writable.txt", "test content", 0o644);44const modeBefore = safeModeFromFile(file);45assert(modeBefore !== undefined, "Mode should be readable");4647ensureUserWritable(file);4849assertEquals(safeModeFromFile(file), modeBefore,50"Mode should be unchanged for already-writable file");51}),52{ ignore: isWindows },53);5455// Simulates the Nix/deb scenario: Deno.copyFileSync from a read-only source56// preserves the read-only mode on the copy. ensureUserWritable must fix it.57unitTest(58"file-permissions - copyFileSync from read-only source then ensureUserWritable",59async () => withTempDir((dir) => {60const src = writeFile(dir, "source.lua", "-- filter code", 0o444);6162// Copy it (this is what quarto create does internally)63const dest = join(dir, "dest.lua");64Deno.copyFileSync(src, dest);6566// Without the fix, dest inherits 0o444 from src67const modeBefore = safeModeFromFile(dest);68assert(modeBefore !== undefined);69assert((modeBefore! & 0o200) === 0, "Copied file should inherit read-only mode from source");7071// Make source writable so cleanup succeeds72Deno.chmodSync(src, 0o644);7374ensureUserWritable(dest);7576assertEquals(safeModeFromFile(dest)! & 0o777, 0o644,77"Copied file should be user-writable after ensureUserWritable");78}),79{ ignore: isWindows },80);818283