importScripts('/resources/testharness.js'); importScripts('resources/sandboxed-fs-test-helpers.js'); importScripts('resources/test-helpers.js'); 'use strict'; const LOCK_WRITE_PERMISSION = { NOT_WRITABLE: 'not writable', WRITABLE: 'writable', }; async function testLockWritePermission(t, fileHandle, createSAHLock) { const syncHandle = await createSAHLock(t, fileHandle); let permission; const writeBuffer = new TextEncoder().encode('Hello Storage Foundation'); try { syncHandle.write(writeBuffer, {at: 0}); permission = LOCK_WRITE_PERMISSION.WRITABLE; } catch (e) { permission = LOCK_WRITE_PERMISSION.NOT_WRITABLE; assert_throws_dom('NoModificationAllowedError', () => { throw e; }); } // truncate and flush should throw a NoModificationAllowedError if an only if // write threw a NoModificationAllowedError. if (permission == LOCK_WRITE_PERMISSION.WRITABLE) { syncHandle.truncate(0); syncHandle.flush(); } else { assert_throws_dom( 'NoModificationAllowedError', () => syncHandle.truncate(0)); assert_throws_dom('NoModificationAllowedError', () => syncHandle.flush()); } return permission; } // Adds tests for expected behaviors of an access handle created in `sahMode` // mode. function lockPropertyTests( sahMode, expectedLockAccess, expectedLockWritePermission) { const createSAHLock = createSAHWithCleanupFactory({mode: sahMode}); directory_test(async (t, rootDir) => { const [fileHandle] = await createFileHandles(rootDir, 'BFS.test'); const {mode} = await createSAHLock(t, fileHandle); assert_equals(mode, sahMode); }, `An access handle in ${sahMode} mode has a mode property equal to` + ` ${sahMode}`); directory_test(async (t, rootDir) => { const [fileHandle] = await createFileHandles(rootDir, 'BFS.test'); assert_equals( await testLockAccess(t, fileHandle, createSAHLock), expectedLockAccess); }, `An access handle in ${sahMode} mode takes a lock that is` + ` ${expectedLockAccess}`); directory_test(async (t, rootDir) => { const [fileHandle] = await createFileHandles(rootDir, 'BFS.test'); assert_equals( await testLockWritePermission(t, fileHandle, createSAHLock), expectedLockWritePermission); }, `An access handle in ${sahMode} mode is ${expectedLockWritePermission}`); // Test interaction with other access handle modes. for (const mode of SAH_MODES) { // Add tests depending on which access handle modes are being tested against // each other. const testingAgainstSelf = mode === sahMode; const testingExclusiveLock = expectedLockAccess === 'exclusive'; const tests = { diffFile: `When there's an open access handle in ${sahMode} mode on a` + ` file, can open another access handle in ${mode} on a different` + ` file`, }; if (!testingAgainstSelf || testingExclusiveLock) { tests.sameFile = `When there's an open access handle in ${sahMode} mode` + ` on a file, cannot open another access handle in ${mode} on that` + ` same file`; } if (testingExclusiveLock) { tests.acquireAfterRelease = `After an access handle in ${sahMode} mode` + ` on a file has been closed, can open another access handle in` + ` ${mode} on the same file`; } if (!testingExclusiveLock && !testingAgainstSelf) { tests.multiAcquireAfterRelease = `After all access handles in` + ` ${sahMode} mode on a file has been closed, can open another` + ` access handle in ${mode} on the same file`; } generateCrossLockTests( createSAHLock, createSAHWithCleanupFactory({mode: mode}), tests); } } directory_test(async (t, rootDir) => { const [fileHandle] = await createFileHandles(rootDir, 'BFS.test'); const syncHandle = await createSAHWithCleanup(t, fileHandle); assert_equals(syncHandle.mode, 'readwrite'); }, 'A sync access handle opens in readwrite mode by default'); lockPropertyTests( 'readwrite', LOCK_ACCESS.EXCLUSIVE, LOCK_WRITE_PERMISSION.WRITABLE); lockPropertyTests( 'read-only', LOCK_ACCESS.SHARED, LOCK_WRITE_PERMISSION.NOT_WRITABLE); lockPropertyTests( 'readwrite-unsafe', LOCK_ACCESS.SHARED, LOCK_WRITE_PERMISSION.WRITABLE); done();