summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/fs/FileSystemFileHandle-sync-access-handle-lock-modes.https.tentative.worker.js
blob: bb82632e185c3f4e9c7c2dd503faabaa054719a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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();