@livestore/wa-sqlite 0.4.0-dev.22 → 0.4.0-dev.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -36
- package/dist/README.md +13 -13
- package/dist/fts5/wa-sqlite.mjs +1 -1
- package/dist/fts5/wa-sqlite.node.mjs +1 -1
- package/dist/fts5/wa-sqlite.node.wasm +0 -0
- package/dist/fts5/wa-sqlite.wasm +0 -0
- package/dist/wa-sqlite-async.mjs +1 -1
- package/dist/wa-sqlite-async.wasm +0 -0
- package/dist/wa-sqlite-jspi.mjs +1 -1
- package/dist/wa-sqlite-jspi.wasm +0 -0
- package/dist/wa-sqlite.mjs +1 -1
- package/dist/wa-sqlite.node.mjs +1 -1
- package/dist/wa-sqlite.node.wasm +0 -0
- package/dist/wa-sqlite.wasm +0 -0
- package/package.json +40 -29
- package/src/FacadeVFS.js +252 -261
- package/src/VFS.js +84 -85
- package/src/WebLocksMixin.js +357 -351
- package/src/examples/AccessHandlePoolVFS.js +185 -194
- package/src/examples/IDBBatchAtomicVFS.js +429 -409
- package/src/examples/IDBMirrorVFS.js +402 -409
- package/src/examples/MemoryAsyncVFS.js +32 -37
- package/src/examples/MemoryVFS.js +71 -75
- package/src/examples/OPFSAdaptiveVFS.js +206 -206
- package/src/examples/OPFSAnyContextVFS.js +141 -140
- package/src/examples/OPFSCoopSyncVFS.js +297 -299
- package/src/examples/OPFSPermutedVFS.js +529 -540
- package/src/examples/README.md +27 -15
- package/src/examples/tag.js +27 -27
- package/src/sqlite-api.js +910 -941
- package/src/sqlite-constants.js +246 -232
- package/src/types/globals.d.ts +52 -52
- package/src/types/index.d.ts +586 -576
- package/test/AccessHandlePoolVFS.test.js +21 -21
- package/test/IDBBatchAtomicVFS.test.js +69 -69
- package/test/IDBMirrorVFS.test.js +21 -21
- package/test/MemoryAsyncVFS.test.js +21 -21
- package/test/MemoryVFS.test.js +21 -21
- package/test/OPFSAdaptiveVFS.test.js +21 -21
- package/test/OPFSAnyContextVFS.test.js +21 -21
- package/test/OPFSCoopSyncVFS.test.js +21 -21
- package/test/OPFSPermutedVFS.test.js +21 -21
- package/test/TestContext.js +44 -41
- package/test/WebLocksMixin.test.js +369 -360
- package/test/api.test.js +23 -23
- package/test/api_exec.js +72 -61
- package/test/api_misc.js +53 -54
- package/test/api_statements.js +271 -279
- package/test/callbacks.test.js +492 -478
- package/test/data/idbv5.json +1135 -1
- package/test/sql.test.js +30 -30
- package/test/sql_0001.js +49 -33
- package/test/sql_0002.js +55 -34
- package/test/sql_0003.js +85 -49
- package/test/sql_0004.js +76 -47
- package/test/sql_0005.js +60 -44
- package/test/test-worker.js +171 -163
- package/test/vfs_xAccess.js +1 -2
- package/test/vfs_xClose.js +50 -49
- package/test/vfs_xOpen.js +73 -72
- package/test/vfs_xRead.js +31 -31
- package/test/vfs_xWrite.js +30 -29
|
@@ -1,521 +1,530 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import * as SQLite from '../src/sqlite-api.js'
|
|
2
|
+
import { WebLocksMixin } from '../src/WebLocksMixin.js'
|
|
3
3
|
|
|
4
4
|
class Tester extends WebLocksMixin(Object) {
|
|
5
5
|
getFilename(fileId) {
|
|
6
|
-
return fileId.toString()
|
|
6
|
+
return fileId.toString()
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
basicTests('exclusive')
|
|
11
|
-
basicTests('shared')
|
|
12
|
-
basicTests('shared+hint')
|
|
10
|
+
basicTests('exclusive')
|
|
11
|
+
basicTests('shared')
|
|
12
|
+
basicTests('shared+hint')
|
|
13
13
|
|
|
14
14
|
function basicTests(policy) {
|
|
15
15
|
beforeEach(async () => {
|
|
16
|
-
await clearAllLocks()
|
|
17
|
-
})
|
|
16
|
+
await clearAllLocks()
|
|
17
|
+
})
|
|
18
18
|
|
|
19
19
|
afterEach(async () => {
|
|
20
|
-
await clearAllLocks()
|
|
21
|
-
})
|
|
20
|
+
await clearAllLocks()
|
|
21
|
+
})
|
|
22
22
|
|
|
23
23
|
describe(`WebLocksMixin basics ${policy}`, () => {
|
|
24
24
|
it('should make normal lock transitions', async () => {
|
|
25
|
-
let rc
|
|
26
|
-
const tester = new Tester(null, null, { lockPolicy: policy })
|
|
25
|
+
let rc
|
|
26
|
+
const tester = new Tester(null, null, { lockPolicy: policy })
|
|
27
27
|
|
|
28
|
-
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
29
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
28
|
+
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
29
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
30
30
|
|
|
31
|
-
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
32
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
31
|
+
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
32
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
33
33
|
|
|
34
|
-
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
35
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
34
|
+
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
35
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
36
36
|
|
|
37
|
-
rc = await tester.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
38
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
37
|
+
rc = await tester.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
38
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
39
39
|
|
|
40
|
-
rc = await tester.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
41
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
40
|
+
rc = await tester.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
41
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
42
42
|
|
|
43
|
-
await expectAsync(clearAllLocks()).toBeResolvedTo(0)
|
|
44
|
-
})
|
|
43
|
+
await expectAsync(clearAllLocks()).toBeResolvedTo(0)
|
|
44
|
+
})
|
|
45
45
|
|
|
46
46
|
it('should make recovery lock transitions', async () => {
|
|
47
|
-
let rc
|
|
48
|
-
const tester = new Tester(null, null, { lockPolicy: policy })
|
|
47
|
+
let rc
|
|
48
|
+
const tester = new Tester(null, null, { lockPolicy: policy })
|
|
49
49
|
|
|
50
|
-
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
51
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
50
|
+
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
51
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
52
52
|
|
|
53
|
-
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
54
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
53
|
+
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
54
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
55
55
|
|
|
56
|
-
rc = await tester.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
57
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
56
|
+
rc = await tester.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
57
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
58
58
|
|
|
59
|
-
rc = await tester.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
60
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
59
|
+
rc = await tester.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
60
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
61
61
|
|
|
62
|
-
await expectAsync(clearAllLocks()).toBeResolvedTo(0)
|
|
63
|
-
})
|
|
62
|
+
await expectAsync(clearAllLocks()).toBeResolvedTo(0)
|
|
63
|
+
})
|
|
64
64
|
|
|
65
65
|
it('should ignore repeated state requests', async () => {
|
|
66
|
-
let rc
|
|
67
|
-
const tester = new Tester(null, null, { lockPolicy: policy })
|
|
68
|
-
|
|
69
|
-
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
70
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
71
|
-
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
72
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
73
|
-
|
|
74
|
-
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
75
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
76
|
-
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
77
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
78
|
-
|
|
79
|
-
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
80
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
81
|
-
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
82
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
83
|
-
|
|
84
|
-
rc = await tester.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
85
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
86
|
-
rc = await tester.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
87
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
88
|
-
|
|
89
|
-
rc = await tester.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
90
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
91
|
-
rc = await tester.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
92
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
93
|
-
|
|
94
|
-
await expectAsync(clearAllLocks()).toBeResolvedTo(0)
|
|
95
|
-
})
|
|
96
|
-
})
|
|
66
|
+
let rc
|
|
67
|
+
const tester = new Tester(null, null, { lockPolicy: policy })
|
|
68
|
+
|
|
69
|
+
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
70
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
71
|
+
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
72
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
73
|
+
|
|
74
|
+
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
75
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
76
|
+
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
77
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
78
|
+
|
|
79
|
+
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
80
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
81
|
+
rc = await tester.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
82
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
83
|
+
|
|
84
|
+
rc = await tester.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
85
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
86
|
+
rc = await tester.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
87
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
88
|
+
|
|
89
|
+
rc = await tester.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
90
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
91
|
+
rc = await tester.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
92
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
93
|
+
|
|
94
|
+
await expectAsync(clearAllLocks()).toBeResolvedTo(0)
|
|
95
|
+
})
|
|
96
|
+
})
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
describe('WebLocksMixin exclusive', () => {
|
|
100
100
|
beforeEach(async () => {
|
|
101
|
-
await clearAllLocks()
|
|
102
|
-
})
|
|
101
|
+
await clearAllLocks()
|
|
102
|
+
})
|
|
103
103
|
|
|
104
104
|
afterEach(async () => {
|
|
105
|
-
await clearAllLocks()
|
|
106
|
-
})
|
|
105
|
+
await clearAllLocks()
|
|
106
|
+
})
|
|
107
107
|
|
|
108
108
|
it('should block multiple SHARED connections', async () => {
|
|
109
|
-
let rc
|
|
110
|
-
const testerA = new Tester(null, null, { lockPolicy: 'exclusive' })
|
|
111
|
-
const testerB = new Tester(null, null, { lockPolicy: 'exclusive' })
|
|
109
|
+
let rc
|
|
110
|
+
const testerA = new Tester(null, null, { lockPolicy: 'exclusive' })
|
|
111
|
+
const testerB = new Tester(null, null, { lockPolicy: 'exclusive' })
|
|
112
112
|
|
|
113
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
114
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
113
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
114
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
115
115
|
|
|
116
|
-
const result = testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
117
|
-
await new Promise(resolve => setTimeout(resolve, 100))
|
|
118
|
-
await expectAsync(result).toBePending()
|
|
116
|
+
const result = testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
117
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
118
|
+
await expectAsync(result).toBePending()
|
|
119
119
|
|
|
120
|
-
rc = await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
121
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
120
|
+
rc = await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
121
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
122
122
|
|
|
123
|
-
await new Promise(resolve => setTimeout(resolve))
|
|
124
|
-
await expectAsync(result).toBeResolvedTo(SQLite.SQLITE_OK)
|
|
123
|
+
await new Promise((resolve) => setTimeout(resolve))
|
|
124
|
+
await expectAsync(result).toBeResolvedTo(SQLite.SQLITE_OK)
|
|
125
125
|
|
|
126
|
-
rc = await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
127
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
128
|
-
})
|
|
126
|
+
rc = await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
127
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
128
|
+
})
|
|
129
129
|
|
|
130
130
|
it('should timeout', async () => {
|
|
131
|
-
let rc
|
|
132
|
-
const testerA = new Tester(null, null, { lockPolicy: 'exclusive', lockTimeout: 5 })
|
|
133
|
-
const testerB = new Tester(null, null, { lockPolicy: 'exclusive', lockTimeout: 5 })
|
|
131
|
+
let rc
|
|
132
|
+
const testerA = new Tester(null, null, { lockPolicy: 'exclusive', lockTimeout: 5 })
|
|
133
|
+
const testerB = new Tester(null, null, { lockPolicy: 'exclusive', lockTimeout: 5 })
|
|
134
134
|
|
|
135
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
136
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
135
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
136
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
137
137
|
|
|
138
|
-
const result = testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
139
|
-
await new Promise(resolve => setTimeout(resolve, 100))
|
|
140
|
-
await expectAsync(result).toBeResolvedTo(SQLite.SQLITE_BUSY)
|
|
138
|
+
const result = testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
139
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
140
|
+
await expectAsync(result).toBeResolvedTo(SQLite.SQLITE_BUSY)
|
|
141
141
|
|
|
142
|
-
rc = await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
143
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
142
|
+
rc = await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
143
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
144
144
|
|
|
145
|
-
await expectAsync(clearAllLocks()).toBeResolvedTo(0)
|
|
146
|
-
})
|
|
147
|
-
})
|
|
145
|
+
await expectAsync(clearAllLocks()).toBeResolvedTo(0)
|
|
146
|
+
})
|
|
147
|
+
})
|
|
148
148
|
|
|
149
149
|
describe('WebLocksMixin shared', () => {
|
|
150
150
|
beforeEach(async () => {
|
|
151
|
-
await clearAllLocks()
|
|
152
|
-
})
|
|
151
|
+
await clearAllLocks()
|
|
152
|
+
})
|
|
153
153
|
|
|
154
154
|
afterEach(async () => {
|
|
155
|
-
await clearAllLocks()
|
|
156
|
-
})
|
|
155
|
+
await clearAllLocks()
|
|
156
|
+
})
|
|
157
157
|
|
|
158
158
|
it('should allow multiple SHARED connections', async () => {
|
|
159
|
-
let rc
|
|
160
|
-
const testerA = new Tester(null, null, { lockPolicy: 'shared' })
|
|
161
|
-
const testerB = new Tester(null, null, { lockPolicy: 'shared' })
|
|
159
|
+
let rc
|
|
160
|
+
const testerA = new Tester(null, null, { lockPolicy: 'shared' })
|
|
161
|
+
const testerB = new Tester(null, null, { lockPolicy: 'shared' })
|
|
162
162
|
|
|
163
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
164
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
163
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
164
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
165
165
|
|
|
166
|
-
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
167
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
166
|
+
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
167
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
168
168
|
|
|
169
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
170
|
-
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
171
|
-
})
|
|
169
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
170
|
+
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
171
|
+
})
|
|
172
172
|
|
|
173
173
|
it('should allow SHARED and RESERVED connections', async () => {
|
|
174
|
-
let rc
|
|
175
|
-
const testerA = new Tester(null, null, { lockPolicy: 'shared' })
|
|
176
|
-
const testerB = new Tester(null, null, { lockPolicy: 'shared' })
|
|
174
|
+
let rc
|
|
175
|
+
const testerA = new Tester(null, null, { lockPolicy: 'shared' })
|
|
176
|
+
const testerB = new Tester(null, null, { lockPolicy: 'shared' })
|
|
177
177
|
|
|
178
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
179
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
180
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
181
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
178
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
179
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
180
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
181
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
182
182
|
|
|
183
|
-
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
184
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
183
|
+
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
184
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
185
185
|
|
|
186
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
187
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
188
|
-
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
189
|
-
})
|
|
186
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
187
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
188
|
+
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
189
|
+
})
|
|
190
190
|
|
|
191
191
|
it('should return BUSY on RESERVED deadlock', async () => {
|
|
192
|
-
let rc
|
|
193
|
-
const testerA = new Tester(null, null, { lockPolicy: 'shared' })
|
|
194
|
-
const testerB = new Tester(null, null, { lockPolicy: 'shared' })
|
|
192
|
+
let rc
|
|
193
|
+
const testerA = new Tester(null, null, { lockPolicy: 'shared' })
|
|
194
|
+
const testerB = new Tester(null, null, { lockPolicy: 'shared' })
|
|
195
195
|
|
|
196
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
197
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
196
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
197
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
198
198
|
|
|
199
|
-
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
200
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
199
|
+
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
200
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
201
201
|
|
|
202
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
203
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
202
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
203
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
204
204
|
|
|
205
|
-
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
206
|
-
expect(rc).toBe(SQLite.SQLITE_BUSY)
|
|
205
|
+
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
206
|
+
expect(rc).toBe(SQLite.SQLITE_BUSY)
|
|
207
207
|
|
|
208
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
209
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
210
|
-
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
211
|
-
})
|
|
208
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
209
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
210
|
+
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
211
|
+
})
|
|
212
212
|
|
|
213
213
|
it('should block EXCLUSIVE until SHARED connections are released', async () => {
|
|
214
|
-
let rc
|
|
215
|
-
const testerA = new Tester(null, null, { lockPolicy: 'shared' })
|
|
216
|
-
const testerB = new Tester(null, null, { lockPolicy: 'shared' })
|
|
214
|
+
let rc
|
|
215
|
+
const testerA = new Tester(null, null, { lockPolicy: 'shared' })
|
|
216
|
+
const testerB = new Tester(null, null, { lockPolicy: 'shared' })
|
|
217
217
|
|
|
218
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
219
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
218
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
219
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
220
220
|
|
|
221
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
222
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
221
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
222
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
223
223
|
|
|
224
|
-
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
225
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
224
|
+
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
225
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
226
226
|
|
|
227
|
-
const result = testerA.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
228
|
-
await new Promise(resolve => setTimeout(resolve, 100))
|
|
229
|
-
await expectAsync(result).toBePending()
|
|
227
|
+
const result = testerA.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
228
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
229
|
+
await expectAsync(result).toBePending()
|
|
230
230
|
|
|
231
|
-
rc = await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
232
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
231
|
+
rc = await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
232
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
233
233
|
|
|
234
|
-
await new Promise(resolve => setTimeout(resolve))
|
|
235
|
-
await expectAsync(result).toBeResolvedTo(SQLite.SQLITE_OK)
|
|
234
|
+
await new Promise((resolve) => setTimeout(resolve))
|
|
235
|
+
await expectAsync(result).toBeResolvedTo(SQLite.SQLITE_OK)
|
|
236
236
|
|
|
237
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
238
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
239
|
-
})
|
|
237
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
238
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
239
|
+
})
|
|
240
240
|
|
|
241
241
|
it('should block SHARED until EXCLUSIVE connection is released', async () => {
|
|
242
|
-
let rc
|
|
243
|
-
const testerA = new Tester(null, null, { lockPolicy: 'shared' })
|
|
244
|
-
const testerB = new Tester(null, null, { lockPolicy: 'shared' })
|
|
242
|
+
let rc
|
|
243
|
+
const testerA = new Tester(null, null, { lockPolicy: 'shared' })
|
|
244
|
+
const testerB = new Tester(null, null, { lockPolicy: 'shared' })
|
|
245
245
|
|
|
246
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
247
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
246
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
247
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
248
248
|
|
|
249
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
250
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
249
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
250
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
251
251
|
|
|
252
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
253
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
252
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
253
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
254
254
|
|
|
255
|
-
const result = testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
256
|
-
await new Promise(resolve => setTimeout(resolve, 100))
|
|
257
|
-
await expectAsync(result).toBePending()
|
|
255
|
+
const result = testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
256
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
257
|
+
await expectAsync(result).toBePending()
|
|
258
258
|
|
|
259
|
-
rc = await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
260
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
259
|
+
rc = await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
260
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
261
261
|
|
|
262
|
-
await new Promise(resolve => setTimeout(resolve))
|
|
263
|
-
await expectAsync(result).toBeResolvedTo(SQLite.SQLITE_OK)
|
|
262
|
+
await new Promise((resolve) => setTimeout(resolve))
|
|
263
|
+
await expectAsync(result).toBeResolvedTo(SQLite.SQLITE_OK)
|
|
264
264
|
|
|
265
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
266
|
-
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
267
|
-
})
|
|
265
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
266
|
+
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
267
|
+
})
|
|
268
268
|
|
|
269
269
|
it('should timeout on SHARED', async () => {
|
|
270
|
-
let rc
|
|
271
|
-
const testerA = new Tester(null, null, { lockPolicy: 'shared', lockTimeout: 5 })
|
|
272
|
-
const testerB = new Tester(null, null, { lockPolicy: 'shared', lockTimeout: 5 })
|
|
270
|
+
let rc
|
|
271
|
+
const testerA = new Tester(null, null, { lockPolicy: 'shared', lockTimeout: 5 })
|
|
272
|
+
const testerB = new Tester(null, null, { lockPolicy: 'shared', lockTimeout: 5 })
|
|
273
273
|
|
|
274
|
-
await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
275
|
-
await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
276
|
-
await testerA.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
274
|
+
await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
275
|
+
await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
276
|
+
await testerA.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
277
277
|
|
|
278
|
-
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
279
|
-
expect(rc).toBe(SQLite.SQLITE_BUSY)
|
|
278
|
+
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
279
|
+
expect(rc).toBe(SQLite.SQLITE_BUSY)
|
|
280
280
|
|
|
281
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
282
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
283
|
-
})
|
|
281
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
282
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
283
|
+
})
|
|
284
284
|
|
|
285
285
|
it('should timeout on EXCLUSIVE', async () => {
|
|
286
|
-
let rc
|
|
287
|
-
const testerA = new Tester(null, null, { lockPolicy: 'shared', lockTimeout: 5 })
|
|
288
|
-
const testerB = new Tester(null, null, { lockPolicy: 'shared', lockTimeout: 5 })
|
|
286
|
+
let rc
|
|
287
|
+
const testerA = new Tester(null, null, { lockPolicy: 'shared', lockTimeout: 5 })
|
|
288
|
+
const testerB = new Tester(null, null, { lockPolicy: 'shared', lockTimeout: 5 })
|
|
289
289
|
|
|
290
|
-
await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
291
|
-
await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
292
|
-
await testerB.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
290
|
+
await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
291
|
+
await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
292
|
+
await testerB.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
293
293
|
|
|
294
|
-
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
295
|
-
expect(rc).toBe(SQLite.SQLITE_BUSY)
|
|
294
|
+
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
295
|
+
expect(rc).toBe(SQLite.SQLITE_BUSY)
|
|
296
296
|
|
|
297
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
298
|
-
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
299
|
-
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
300
|
-
})
|
|
301
|
-
})
|
|
297
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
298
|
+
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
299
|
+
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
300
|
+
})
|
|
301
|
+
})
|
|
302
302
|
|
|
303
303
|
describe('WebLocksMixin shared+hint', () => {
|
|
304
304
|
beforeEach(async () => {
|
|
305
|
-
await clearAllLocks()
|
|
306
|
-
})
|
|
305
|
+
await clearAllLocks()
|
|
306
|
+
})
|
|
307
307
|
|
|
308
308
|
afterEach(async () => {
|
|
309
|
-
await clearAllLocks()
|
|
310
|
-
})
|
|
309
|
+
await clearAllLocks()
|
|
310
|
+
})
|
|
311
311
|
|
|
312
312
|
it('should allow multiple SHARED connections', async () => {
|
|
313
|
-
let rc
|
|
314
|
-
const testerA = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
315
|
-
const testerB = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
313
|
+
let rc
|
|
314
|
+
const testerA = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
315
|
+
const testerB = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
316
316
|
|
|
317
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
318
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
317
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
318
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
319
319
|
|
|
320
|
-
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
321
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
320
|
+
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
321
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
322
322
|
|
|
323
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
324
|
-
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
325
|
-
})
|
|
323
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
324
|
+
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
325
|
+
})
|
|
326
326
|
|
|
327
327
|
it('should allow SHARED and RESERVED connections', async () => {
|
|
328
|
-
let rc
|
|
329
|
-
const testerA = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
330
|
-
const testerB = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
328
|
+
let rc
|
|
329
|
+
const testerA = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
330
|
+
const testerB = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
331
331
|
|
|
332
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
333
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
334
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
335
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
332
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
333
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
334
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
335
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
336
336
|
|
|
337
|
-
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
338
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
337
|
+
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
338
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
339
339
|
|
|
340
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
341
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
342
|
-
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
343
|
-
})
|
|
340
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
341
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
342
|
+
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
343
|
+
})
|
|
344
344
|
|
|
345
345
|
it('should return BUSY on RESERVED deadlock', async () => {
|
|
346
|
-
let rc
|
|
347
|
-
const testerA = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
348
|
-
const testerB = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
346
|
+
let rc
|
|
347
|
+
const testerA = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
348
|
+
const testerB = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
349
349
|
|
|
350
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
351
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
350
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
351
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
352
352
|
|
|
353
|
-
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
354
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
353
|
+
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
354
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
355
355
|
|
|
356
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
357
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
356
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
357
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
358
358
|
|
|
359
|
-
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
360
|
-
expect(rc).toBe(SQLite.SQLITE_BUSY)
|
|
359
|
+
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
360
|
+
expect(rc).toBe(SQLite.SQLITE_BUSY)
|
|
361
361
|
|
|
362
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
363
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
364
|
-
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
365
|
-
})
|
|
362
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
363
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
364
|
+
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
365
|
+
})
|
|
366
366
|
|
|
367
367
|
it('should block EXCLUSIVE until SHARED connections are released', async () => {
|
|
368
|
-
let rc
|
|
369
|
-
const testerA = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
370
|
-
const testerB = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
368
|
+
let rc
|
|
369
|
+
const testerA = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
370
|
+
const testerB = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
371
371
|
|
|
372
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
373
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
372
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
373
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
374
374
|
|
|
375
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
376
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
375
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
376
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
377
377
|
|
|
378
|
-
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
379
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
378
|
+
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
379
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
380
380
|
|
|
381
|
-
const result = testerA.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
382
|
-
await new Promise(resolve => setTimeout(resolve, 100))
|
|
383
|
-
await expectAsync(result).toBePending()
|
|
381
|
+
const result = testerA.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
382
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
383
|
+
await expectAsync(result).toBePending()
|
|
384
384
|
|
|
385
|
-
rc = await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
386
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
385
|
+
rc = await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
386
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
387
387
|
|
|
388
|
-
await new Promise(resolve => setTimeout(resolve))
|
|
389
|
-
await expectAsync(result).toBeResolvedTo(SQLite.SQLITE_OK)
|
|
388
|
+
await new Promise((resolve) => setTimeout(resolve))
|
|
389
|
+
await expectAsync(result).toBeResolvedTo(SQLite.SQLITE_OK)
|
|
390
390
|
|
|
391
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
392
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
393
|
-
})
|
|
391
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
392
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
393
|
+
})
|
|
394
394
|
|
|
395
395
|
it('should block SHARED until EXCLUSIVE connection is released', async () => {
|
|
396
|
-
let rc
|
|
397
|
-
const testerA = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
398
|
-
const testerB = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
396
|
+
let rc
|
|
397
|
+
const testerA = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
398
|
+
const testerB = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
399
399
|
|
|
400
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
401
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
400
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
401
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
402
402
|
|
|
403
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
404
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
403
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
404
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
405
405
|
|
|
406
|
-
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
407
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
406
|
+
rc = await testerA.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
407
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
408
408
|
|
|
409
|
-
const result = testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
410
|
-
await new Promise(resolve => setTimeout(resolve, 100))
|
|
411
|
-
await expectAsync(result).toBePending()
|
|
409
|
+
const result = testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
410
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
411
|
+
await expectAsync(result).toBePending()
|
|
412
412
|
|
|
413
|
-
rc = await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
414
|
-
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
413
|
+
rc = await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
414
|
+
expect(rc).toBe(SQLite.SQLITE_OK)
|
|
415
415
|
|
|
416
|
-
await new Promise(resolve => setTimeout(resolve))
|
|
417
|
-
await expectAsync(result).toBeResolvedTo(SQLite.SQLITE_OK)
|
|
416
|
+
await new Promise((resolve) => setTimeout(resolve))
|
|
417
|
+
await expectAsync(result).toBeResolvedTo(SQLite.SQLITE_OK)
|
|
418
418
|
|
|
419
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
420
|
-
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
421
|
-
})
|
|
419
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
420
|
+
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
421
|
+
})
|
|
422
422
|
|
|
423
423
|
it('should timeout on SHARED', async () => {
|
|
424
|
-
let rc
|
|
425
|
-
const testerA = new Tester(null, null, { lockPolicy: 'shared+hint', lockTimeout: 5 })
|
|
426
|
-
const testerB = new Tester(null, null, { lockPolicy: 'shared+hint', lockTimeout: 5 })
|
|
424
|
+
let rc
|
|
425
|
+
const testerA = new Tester(null, null, { lockPolicy: 'shared+hint', lockTimeout: 5 })
|
|
426
|
+
const testerB = new Tester(null, null, { lockPolicy: 'shared+hint', lockTimeout: 5 })
|
|
427
427
|
|
|
428
|
-
await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
429
|
-
await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
430
|
-
await testerA.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
428
|
+
await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
429
|
+
await testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
430
|
+
await testerA.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
431
431
|
|
|
432
|
-
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
433
|
-
expect(rc).toBe(SQLite.SQLITE_BUSY)
|
|
432
|
+
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
433
|
+
expect(rc).toBe(SQLite.SQLITE_BUSY)
|
|
434
434
|
|
|
435
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
436
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
437
|
-
})
|
|
435
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
436
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
437
|
+
})
|
|
438
438
|
|
|
439
439
|
it('should timeout on EXCLUSIVE', async () => {
|
|
440
|
-
let rc
|
|
441
|
-
const testerA = new Tester(null, null, { lockPolicy: 'shared+hint', lockTimeout: 5 })
|
|
442
|
-
const testerB = new Tester(null, null, { lockPolicy: 'shared+hint', lockTimeout: 5 })
|
|
440
|
+
let rc
|
|
441
|
+
const testerA = new Tester(null, null, { lockPolicy: 'shared+hint', lockTimeout: 5 })
|
|
442
|
+
const testerB = new Tester(null, null, { lockPolicy: 'shared+hint', lockTimeout: 5 })
|
|
443
443
|
|
|
444
|
-
await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
445
|
-
await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
446
|
-
await testerB.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
444
|
+
await testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
445
|
+
await testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
446
|
+
await testerB.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
447
447
|
|
|
448
|
-
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
449
|
-
expect(rc).toBe(SQLite.SQLITE_BUSY)
|
|
448
|
+
rc = await testerB.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
449
|
+
expect(rc).toBe(SQLite.SQLITE_BUSY)
|
|
450
450
|
|
|
451
|
-
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
452
|
-
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
453
|
-
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
454
|
-
})
|
|
451
|
+
await testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
452
|
+
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
453
|
+
await testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
454
|
+
})
|
|
455
455
|
|
|
456
456
|
it('should not deadlock with hint', async () => {
|
|
457
|
-
let rc
|
|
458
|
-
const testerA = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
459
|
-
const testerB = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
460
|
-
|
|
461
|
-
const resultA = Promise.resolve()
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
457
|
+
let rc
|
|
458
|
+
const testerA = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
459
|
+
const testerB = new Tester(null, null, { lockPolicy: 'shared+hint' })
|
|
460
|
+
|
|
461
|
+
const resultA = Promise.resolve()
|
|
462
|
+
.then(() => {
|
|
463
|
+
testerA.jFileControl(1, WebLocksMixin.WRITE_HINT_OP_CODE, null)
|
|
464
|
+
return testerA.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
465
|
+
})
|
|
466
|
+
.then((result) => {
|
|
467
|
+
if (result !== SQLite.SQLITE_OK) throw Object.assign(new Error('failed'), { result })
|
|
468
|
+
return testerA.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
469
|
+
})
|
|
470
|
+
.then((result) => {
|
|
471
|
+
if (result !== SQLite.SQLITE_OK) throw Object.assign(new Error('failed'), { result })
|
|
472
|
+
return testerA.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
473
|
+
})
|
|
474
|
+
.then((result) => {
|
|
475
|
+
if (result !== SQLite.SQLITE_OK) throw Object.assign(new Error('failed'), { result })
|
|
476
|
+
return testerA.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
477
|
+
})
|
|
478
|
+
.then((result) => {
|
|
479
|
+
if (result !== SQLite.SQLITE_OK) throw Object.assign(new Error('failed'), { result })
|
|
480
|
+
return testerA.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
481
|
+
})
|
|
482
|
+
|
|
483
|
+
const resultB = Promise.resolve()
|
|
484
|
+
.then(() => {
|
|
485
|
+
testerB.jFileControl(1, WebLocksMixin.WRITE_HINT_OP_CODE, null)
|
|
486
|
+
return testerB.jLock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
487
|
+
})
|
|
488
|
+
.then((result) => {
|
|
489
|
+
if (result !== SQLite.SQLITE_OK) throw Object.assign(new Error('failed'), { result })
|
|
490
|
+
return testerB.jLock(1, SQLite.SQLITE_LOCK_RESERVED)
|
|
491
|
+
})
|
|
492
|
+
.then((result) => {
|
|
493
|
+
if (result !== SQLite.SQLITE_OK) throw Object.assign(new Error('failed'), { result })
|
|
494
|
+
return testerB.jLock(1, SQLite.SQLITE_LOCK_EXCLUSIVE)
|
|
495
|
+
})
|
|
496
|
+
.then((result) => {
|
|
497
|
+
if (result !== SQLite.SQLITE_OK) throw Object.assign(new Error('failed'), { result })
|
|
498
|
+
return testerB.jUnlock(1, SQLite.SQLITE_LOCK_SHARED)
|
|
499
|
+
})
|
|
500
|
+
.then((result) => {
|
|
501
|
+
if (result !== SQLite.SQLITE_OK) throw Object.assign(new Error('failed'), { result })
|
|
502
|
+
return testerB.jUnlock(1, SQLite.SQLITE_LOCK_NONE)
|
|
503
|
+
})
|
|
504
|
+
|
|
505
|
+
await expectAsync(resultA).toBeResolvedTo(SQLite.SQLITE_OK)
|
|
506
|
+
await expectAsync(resultB).toBeResolvedTo(SQLite.SQLITE_OK)
|
|
507
|
+
})
|
|
508
|
+
})
|
|
499
509
|
|
|
500
510
|
async function clearAllLocks() {
|
|
501
|
-
await new Promise(resolve => setTimeout(resolve))
|
|
511
|
+
await new Promise((resolve) => setTimeout(resolve))
|
|
502
512
|
|
|
503
|
-
let count = 0
|
|
513
|
+
let count = 0
|
|
504
514
|
while (true) {
|
|
505
|
-
const locks = await navigator.locks.query()
|
|
515
|
+
const locks = await navigator.locks.query()
|
|
506
516
|
const lockNames = [...locks.held, ...locks.pending]
|
|
507
|
-
.map(lock => lock.name)
|
|
508
|
-
.filter(name => name.startsWith('lock##'))
|
|
517
|
+
.map((lock) => lock.name)
|
|
518
|
+
.filter((name) => name.startsWith('lock##'))
|
|
509
519
|
if (lockNames.length === 0) {
|
|
510
|
-
break
|
|
520
|
+
break
|
|
511
521
|
}
|
|
512
522
|
|
|
513
523
|
for (const name of new Set(lockNames)) {
|
|
514
|
-
await navigator.locks.request(name, { steal: true }, async lock => {
|
|
515
|
-
|
|
516
|
-
count++;
|
|
524
|
+
await navigator.locks.request(name, { steal: true }, async (lock) => {})
|
|
525
|
+
count++
|
|
517
526
|
}
|
|
518
|
-
await new Promise(resolve => setTimeout(resolve))
|
|
527
|
+
await new Promise((resolve) => setTimeout(resolve))
|
|
519
528
|
}
|
|
520
|
-
return count
|
|
521
|
-
}
|
|
529
|
+
return count
|
|
530
|
+
}
|