mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Internal refactoring in opfs-sahpool. Move OPFS tests to the end of tester1.c-cpp.js.
FossilOrigin-Name: 6bd5a7413dd830ca41b587a2826fb599a2196fb0186646a2333500f950b3cf4d
This commit is contained in:
@ -89,7 +89,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
|
|
||||||
const optionDefaults = Object.assign(Object.create(null),{
|
const optionDefaults = Object.assign(Object.create(null),{
|
||||||
name: 'opfs-sahpool',
|
name: 'opfs-sahpool',
|
||||||
directory: undefined,
|
directory: undefined /* derived from .name */,
|
||||||
initialCapacity: 6,
|
initialCapacity: 6,
|
||||||
clearOnInit: false,
|
clearOnInit: false,
|
||||||
verbosity: 2 /*3+ == everything, 2 == warnings+errors, 1 == errors only*/
|
verbosity: 2 /*3+ == everything, 2 == warnings+errors, 1 == errors only*/
|
||||||
@ -390,6 +390,21 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFileForPtr(ptr){
|
||||||
|
return this.mapIdToFile.get(ptr);
|
||||||
|
}
|
||||||
|
setFileForPtr(ptr,file){
|
||||||
|
if(file) this.mapIdToFile.set(ptr, file);
|
||||||
|
else this.mapIdToFile.delete(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasFilename(name){
|
||||||
|
return this.mapFilenameToSAH.has(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
getSAHForPath(path){
|
||||||
|
return this.mapFilenameToSAH.get(path);
|
||||||
|
}
|
||||||
}/*class OpfsSAHPool*/;
|
}/*class OpfsSAHPool*/;
|
||||||
|
|
||||||
|
|
||||||
@ -576,6 +591,13 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
the default directory. If no directory is explicitly provided
|
the default directory. If no directory is explicitly provided
|
||||||
then a directory name is synthesized from the `name` option.
|
then a directory name is synthesized from the `name` option.
|
||||||
|
|
||||||
|
Peculiarities of this VFS:
|
||||||
|
|
||||||
|
- Paths given to it _must_ be absolute. Relative paths will not
|
||||||
|
be properly recognized. This is arguably a bug but correcting it
|
||||||
|
requires some hoop-jumping and memory allocation in routines
|
||||||
|
which should not be allocating.
|
||||||
|
|
||||||
|
|
||||||
The API for the utility object passed on by this function's
|
The API for the utility object passed on by this function's
|
||||||
Promise, in alphabetical order...
|
Promise, in alphabetical order...
|
||||||
@ -673,7 +695,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
throw new Error("Just testing rejection.");
|
throw new Error("Just testing rejection.");
|
||||||
}
|
}
|
||||||
if(initPromises[vfsName]){
|
if(initPromises[vfsName]){
|
||||||
console.warn("Returning same OpfsSAHPool result",options,vfsName,initPromises[vfsName]);
|
//console.warn("Returning same OpfsSAHPool result",options,vfsName,initPromises[vfsName]);
|
||||||
return initPromises[vfsName];
|
return initPromises[vfsName];
|
||||||
}
|
}
|
||||||
if(!globalThis.FileSystemHandle ||
|
if(!globalThis.FileSystemHandle ||
|
||||||
@ -699,13 +721,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
const opfsVfs = new capi.sqlite3_vfs()
|
const opfsVfs = new capi.sqlite3_vfs()
|
||||||
.addOnDispose(()=>opfsIoMethods.dispose());
|
.addOnDispose(()=>opfsIoMethods.dispose());
|
||||||
|
|
||||||
const promiseReject = (err)=>{
|
|
||||||
error("rejecting promise:",err);
|
|
||||||
opfsVfs.dispose();
|
|
||||||
initPromises[vfsName] = Promise.reject(err);
|
|
||||||
throw err;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* We fetch the default VFS so that we can inherit some
|
/* We fetch the default VFS so that we can inherit some
|
||||||
methods from it. */
|
methods from it. */
|
||||||
const pDVfs = capi.sqlite3_vfs_find(null);
|
const pDVfs = capi.sqlite3_vfs_find(null);
|
||||||
@ -755,13 +770,13 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
},
|
},
|
||||||
xClose: function(pFile){
|
xClose: function(pFile){
|
||||||
thePool.storeErr();
|
thePool.storeErr();
|
||||||
const file = thePool.mapIdToFile.get(pFile);
|
const file = thePool.getFileForPtr(pFile);
|
||||||
if(file) {
|
if(file) {
|
||||||
try{
|
try{
|
||||||
log(`xClose ${file.path}`);
|
log(`xClose ${file.path}`);
|
||||||
if(file.sq3File) file.sq3File.dispose();
|
if(file.sq3File) file.sq3File.dispose();
|
||||||
file.sah.flush();
|
file.sah.flush();
|
||||||
thePool.mapIdToFile.delete(pFile);
|
thePool.setFileForPtr(pFile,0);
|
||||||
if(file.flags & capi.SQLITE_OPEN_DELETEONCLOSE){
|
if(file.flags & capi.SQLITE_OPEN_DELETEONCLOSE){
|
||||||
thePool.deletePath(file.path);
|
thePool.deletePath(file.path);
|
||||||
}
|
}
|
||||||
@ -780,7 +795,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
},
|
},
|
||||||
xFileSize: function(pFile,pSz64){
|
xFileSize: function(pFile,pSz64){
|
||||||
log(`xFileSize`);
|
log(`xFileSize`);
|
||||||
const file = thePool.mapIdToFile.get(pFile);
|
const file = thePool.getFileForPtr(pFile);
|
||||||
const size = file.sah.getSize() - HEADER_OFFSET_DATA;
|
const size = file.sah.getSize() - HEADER_OFFSET_DATA;
|
||||||
//log(`xFileSize ${file.path} ${size}`);
|
//log(`xFileSize ${file.path} ${size}`);
|
||||||
wasm.poke64(pSz64, BigInt(size));
|
wasm.poke64(pSz64, BigInt(size));
|
||||||
@ -789,14 +804,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
xLock: function(pFile,lockType){
|
xLock: function(pFile,lockType){
|
||||||
log(`xLock ${lockType}`);
|
log(`xLock ${lockType}`);
|
||||||
thePool.storeErr();
|
thePool.storeErr();
|
||||||
const file = thePool.mapIdToFile.get(pFile);
|
const file = thePool.getFileForPtr(pFile);
|
||||||
file.lockType = lockType;
|
file.lockType = lockType;
|
||||||
return 0;
|
return 0;
|
||||||
},
|
},
|
||||||
xRead: function(pFile,pDest,n,offset64){
|
xRead: function(pFile,pDest,n,offset64){
|
||||||
log(`xRead ${n}@${offset64}`);
|
log(`xRead ${n}@${offset64}`);
|
||||||
thePool.storeErr();
|
thePool.storeErr();
|
||||||
const file = thePool.mapIdToFile.get(pFile);
|
const file = thePool.getFileForPtr(pFile);
|
||||||
log(`xRead ${file.path} ${n} ${offset64}`);
|
log(`xRead ${file.path} ${n} ${offset64}`);
|
||||||
try {
|
try {
|
||||||
const nRead = file.sah.read(
|
const nRead = file.sah.read(
|
||||||
@ -819,7 +834,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
xSync: function(pFile,flags){
|
xSync: function(pFile,flags){
|
||||||
log(`xSync ${flags}`);
|
log(`xSync ${flags}`);
|
||||||
thePool.storeErr();
|
thePool.storeErr();
|
||||||
const file = thePool.mapIdToFile.get(pFile);
|
const file = thePool.getFileForPtr(pFile);
|
||||||
//log(`xSync ${file.path} ${flags}`);
|
//log(`xSync ${file.path} ${flags}`);
|
||||||
try{
|
try{
|
||||||
file.sah.flush();
|
file.sah.flush();
|
||||||
@ -832,7 +847,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
xTruncate: function(pFile,sz64){
|
xTruncate: function(pFile,sz64){
|
||||||
log(`xTruncate ${sz64}`);
|
log(`xTruncate ${sz64}`);
|
||||||
thePool.storeErr();
|
thePool.storeErr();
|
||||||
const file = thePool.mapIdToFile.get(pFile);
|
const file = thePool.getFileForPtr(pFile);
|
||||||
//log(`xTruncate ${file.path} ${iSize}`);
|
//log(`xTruncate ${file.path} ${iSize}`);
|
||||||
try{
|
try{
|
||||||
file.sah.truncate(HEADER_OFFSET_DATA + Number(sz64));
|
file.sah.truncate(HEADER_OFFSET_DATA + Number(sz64));
|
||||||
@ -844,13 +859,13 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
},
|
},
|
||||||
xUnlock: function(pFile,lockType){
|
xUnlock: function(pFile,lockType){
|
||||||
log('xUnlock');
|
log('xUnlock');
|
||||||
const file = thePool.mapIdToFile.get(pFile);
|
const file = thePool.getFileForPtr(pFile);
|
||||||
file.lockType = lockType;
|
file.lockType = lockType;
|
||||||
return 0;
|
return 0;
|
||||||
},
|
},
|
||||||
xWrite: function(pFile,pSrc,n,offset64){
|
xWrite: function(pFile,pSrc,n,offset64){
|
||||||
thePool.storeErr();
|
thePool.storeErr();
|
||||||
const file = thePool.mapIdToFile.get(pFile);
|
const file = thePool.getFileForPtr(pFile);
|
||||||
log(`xWrite ${file.path} ${n} ${offset64}`);
|
log(`xWrite ${file.path} ${n} ${offset64}`);
|
||||||
try{
|
try{
|
||||||
const nBytes = file.sah.write(
|
const nBytes = file.sah.write(
|
||||||
@ -870,13 +885,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
*/
|
*/
|
||||||
const vfsMethods = {
|
const vfsMethods = {
|
||||||
xAccess: function(pVfs,zName,flags,pOut){
|
xAccess: function(pVfs,zName,flags,pOut){
|
||||||
log(`xAccess ${wasm.cstrToJs(zName)}`);
|
//log(`xAccess ${wasm.cstrToJs(zName)}`);
|
||||||
thePool.storeErr();
|
thePool.storeErr();
|
||||||
try{
|
try{
|
||||||
const name = this.getPath(zName);
|
const name = thePool.getPath(zName);
|
||||||
wasm.poke32(pOut, thePool.mapFilenameToSAH.has(name) ? 1 : 0);
|
wasm.poke32(pOut, thePool.hasFilename(name) ? 1 : 0);
|
||||||
}catch(e){
|
}catch(e){
|
||||||
/*ignored*/;
|
/*ignored*/
|
||||||
|
wasm.poke32(pOut, 0);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
},
|
},
|
||||||
@ -931,7 +947,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
const path = (zName && wasm.peek8(zName))
|
const path = (zName && wasm.peek8(zName))
|
||||||
? thePool.getPath(zName)
|
? thePool.getPath(zName)
|
||||||
: getRandomName();
|
: getRandomName();
|
||||||
let sah = thePool.mapFilenameToSAH.get(path);
|
let sah = thePool.getSAHForPath(path);
|
||||||
if(!sah && (flags & capi.SQLITE_OPEN_CREATE)) {
|
if(!sah && (flags & capi.SQLITE_OPEN_CREATE)) {
|
||||||
// File not found so try to create it.
|
// File not found so try to create it.
|
||||||
if(thePool.getFileCount() < thePool.getCapacity()) {
|
if(thePool.getFileCount() < thePool.getCapacity()) {
|
||||||
@ -949,7 +965,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
// Subsequent methods are only passed the file pointer, so
|
// Subsequent methods are only passed the file pointer, so
|
||||||
// map the relevant info we need to that pointer.
|
// map the relevant info we need to that pointer.
|
||||||
const file = {path, flags, sah};
|
const file = {path, flags, sah};
|
||||||
thePool.mapIdToFile.set(pFile, file);
|
thePool.setFileForPtr(pFile, file);
|
||||||
wasm.poke32(pOutFlags, flags);
|
wasm.poke32(pOutFlags, flags);
|
||||||
file.sq3File = new capi.sqlite3_file(pFile);
|
file.sq3File = new capi.sqlite3_file(pFile);
|
||||||
file.sq3File.$pMethods = opfsIoMethods.pointer;
|
file.sq3File.$pMethods = opfsIoMethods.pointer;
|
||||||
@ -1020,6 +1036,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
log("VFS initialized.");
|
log("VFS initialized.");
|
||||||
return poolUtil;
|
return poolUtil;
|
||||||
});
|
});
|
||||||
}).catch(promiseReject);
|
}).catch((err)=>{
|
||||||
|
error("rejecting promise:",err);
|
||||||
|
opfsVfs.dispose();
|
||||||
|
return initPromises[vfsName] = Promise.reject(err);
|
||||||
|
});
|
||||||
}/*installOpfsSAHPoolVfs()*/;
|
}/*installOpfsSAHPoolVfs()*/;
|
||||||
}/*sqlite3ApiBootstrap.initializers*/);
|
}/*sqlite3ApiBootstrap.initializers*/);
|
||||||
|
@ -2634,199 +2634,6 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
|||||||
}/*kvvfs sqlite3_js_vfs_create_file()*/)
|
}/*kvvfs sqlite3_js_vfs_create_file()*/)
|
||||||
;/* end kvvfs tests */
|
;/* end kvvfs tests */
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
|
||||||
T.g('OPFS: Origin-Private File System',
|
|
||||||
(sqlite3)=>(sqlite3.capi.sqlite3_vfs_find("opfs")
|
|
||||||
|| 'requires "opfs" VFS'))
|
|
||||||
.t({
|
|
||||||
name: 'OPFS db sanity checks',
|
|
||||||
test: async function(sqlite3){
|
|
||||||
const filename = this.opfsDbFile = 'sqlite3-tester1.db';
|
|
||||||
const pVfs = this.opfsVfs = capi.sqlite3_vfs_find('opfs');
|
|
||||||
T.assert(pVfs);
|
|
||||||
const unlink = this.opfsUnlink =
|
|
||||||
(fn=filename)=>{wasm.sqlite3_wasm_vfs_unlink(pVfs,fn)};
|
|
||||||
unlink();
|
|
||||||
let db = new sqlite3.oo1.OpfsDb(filename);
|
|
||||||
try {
|
|
||||||
db.exec([
|
|
||||||
'create table p(a);',
|
|
||||||
'insert into p(a) values(1),(2),(3)'
|
|
||||||
]);
|
|
||||||
T.assert(3 === db.selectValue('select count(*) from p'));
|
|
||||||
db.close();
|
|
||||||
db = new sqlite3.oo1.OpfsDb(filename);
|
|
||||||
db.exec('insert into p(a) values(4),(5),(6)');
|
|
||||||
T.assert(6 === db.selectValue('select count(*) from p'));
|
|
||||||
this.opfsDbExport = capi.sqlite3_js_db_export(db);
|
|
||||||
T.assert(this.opfsDbExport instanceof Uint8Array)
|
|
||||||
.assert(this.opfsDbExport.byteLength>0
|
|
||||||
&& 0===this.opfsDbExport.byteLength % 512);
|
|
||||||
}finally{
|
|
||||||
db.close();
|
|
||||||
unlink();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}/*OPFS db sanity checks*/)
|
|
||||||
.t({
|
|
||||||
name: 'OPFS export/import',
|
|
||||||
test: async function(sqlite3){
|
|
||||||
let db;
|
|
||||||
try {
|
|
||||||
const exp = this.opfsDbExport;
|
|
||||||
delete this.opfsDbExport;
|
|
||||||
capi.sqlite3_js_vfs_create_file("opfs", this.opfsDbFile, exp);
|
|
||||||
const db = new sqlite3.oo1.OpfsDb(this.opfsDbFile);
|
|
||||||
T.assert(6 === db.selectValue('select count(*) from p'));
|
|
||||||
}finally{
|
|
||||||
if(db) db.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}/*OPFS export/import*/)
|
|
||||||
.t({
|
|
||||||
name: 'OPFS utility APIs and sqlite3_js_vfs_create_file()',
|
|
||||||
test: async function(sqlite3){
|
|
||||||
const filename = this.opfsDbFile;
|
|
||||||
const pVfs = this.opfsVfs;
|
|
||||||
const unlink = this.opfsUnlink;
|
|
||||||
T.assert(filename && pVfs && !!unlink);
|
|
||||||
delete this.opfsDbFile;
|
|
||||||
delete this.opfsVfs;
|
|
||||||
delete this.opfsUnlink;
|
|
||||||
unlink();
|
|
||||||
// Sanity-test sqlite3_js_vfs_create_file()...
|
|
||||||
/**************************************************************
|
|
||||||
ATTENTION CLIENT-SIDE USERS: sqlite3.opfs is NOT intended
|
|
||||||
for client-side use. It is only for this project's own
|
|
||||||
internal use. Its APIs are subject to change or removal at
|
|
||||||
any time.
|
|
||||||
***************************************************************/
|
|
||||||
const opfs = sqlite3.opfs;
|
|
||||||
const fSize = 1379;
|
|
||||||
let sh;
|
|
||||||
try{
|
|
||||||
T.assert(!(await opfs.entryExists(filename)));
|
|
||||||
capi.sqlite3_js_vfs_create_file(
|
|
||||||
pVfs, filename, null, fSize
|
|
||||||
);
|
|
||||||
T.assert(await opfs.entryExists(filename));
|
|
||||||
let fh = await opfs.rootDirectory.getFileHandle(filename);
|
|
||||||
sh = await fh.createSyncAccessHandle();
|
|
||||||
T.assert(fSize === await sh.getSize());
|
|
||||||
await sh.close();
|
|
||||||
sh = undefined;
|
|
||||||
unlink();
|
|
||||||
T.assert(!(await opfs.entryExists(filename)));
|
|
||||||
|
|
||||||
const ba = new Uint8Array([1,2,3,4,5]);
|
|
||||||
capi.sqlite3_js_vfs_create_file(
|
|
||||||
"opfs", filename, ba
|
|
||||||
);
|
|
||||||
T.assert(await opfs.entryExists(filename));
|
|
||||||
fh = await opfs.rootDirectory.getFileHandle(filename);
|
|
||||||
sh = await fh.createSyncAccessHandle();
|
|
||||||
T.assert(ba.byteLength === await sh.getSize());
|
|
||||||
await sh.close();
|
|
||||||
sh = undefined;
|
|
||||||
unlink();
|
|
||||||
|
|
||||||
T.mustThrowMatching(()=>{
|
|
||||||
capi.sqlite3_js_vfs_create_file(
|
|
||||||
"no-such-vfs", filename, ba
|
|
||||||
);
|
|
||||||
}, "SQLITE_NOTFOUND: Unknown sqlite3_vfs name: no-such-vfs");
|
|
||||||
}finally{
|
|
||||||
if(sh) await sh.close();
|
|
||||||
unlink();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some sanity checks of the opfs utility functions...
|
|
||||||
const testDir = '/sqlite3-opfs-'+opfs.randomFilename(12);
|
|
||||||
const aDir = testDir+'/test/dir';
|
|
||||||
T.assert(await opfs.mkdir(aDir), "mkdir failed")
|
|
||||||
.assert(await opfs.mkdir(aDir), "mkdir must pass if the dir exists")
|
|
||||||
.assert(!(await opfs.unlink(testDir+'/test')), "delete 1 should have failed (dir not empty)")
|
|
||||||
.assert((await opfs.unlink(testDir+'/test/dir')), "delete 2 failed")
|
|
||||||
.assert(!(await opfs.unlink(testDir+'/test/dir')),
|
|
||||||
"delete 2b should have failed (dir already deleted)")
|
|
||||||
.assert((await opfs.unlink(testDir, true)), "delete 3 failed")
|
|
||||||
.assert(!(await opfs.entryExists(testDir)),
|
|
||||||
"entryExists(",testDir,") should have failed");
|
|
||||||
}
|
|
||||||
}/*OPFS util sanity checks*/)
|
|
||||||
;/* end OPFS tests */
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
|
||||||
T.g('OPFS SyncAccessHandle Pool VFS',
|
|
||||||
(sqlite3)=>(hasOpfs() || "requires OPFS APIs"))
|
|
||||||
.t({
|
|
||||||
name: 'SAH sanity checks',
|
|
||||||
test: async function(sqlite3){
|
|
||||||
T.assert(!sqlite3.capi.sqlite3_vfs_find(sahPoolConfig.name))
|
|
||||||
.assert(sqlite3.capi.sqlite3_js_vfs_list().indexOf(sahPoolConfig.name) < 0)
|
|
||||||
const inst = sqlite3.installOpfsSAHPoolVfs,
|
|
||||||
catcher = (e)=>{
|
|
||||||
error("Cannot load SAH pool VFS.",
|
|
||||||
"This might not be a problem,",
|
|
||||||
"depending on the environment.");
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
let u1, u2;
|
|
||||||
const P1 = inst(sahPoolConfig).then(u=>u1 = u).catch(catcher),
|
|
||||||
P2 = inst(sahPoolConfig).then(u=>u2 = u).catch(catcher);
|
|
||||||
await Promise.all([P1, P2]);
|
|
||||||
if(!P1) return;
|
|
||||||
T.assert(u1 === u2)
|
|
||||||
.assert(sahPoolConfig.name === u1.vfsName)
|
|
||||||
.assert(sqlite3.capi.sqlite3_vfs_find(sahPoolConfig.name))
|
|
||||||
.assert(u1.getCapacity() >= sahPoolConfig.initialCapacity
|
|
||||||
/* If a test fails before we get to nuke the VFS, we
|
|
||||||
can have more than the initial capacity on the next
|
|
||||||
run. */)
|
|
||||||
.assert(u1.getCapacity() + 2 === (await u2.addCapacity(2)))
|
|
||||||
.assert(2 === (await u2.reduceCapacity(2)))
|
|
||||||
.assert(sqlite3.oo1.OpfsSAHPool.default instanceof Function)
|
|
||||||
.assert(sqlite3.oo1.OpfsSAHPool.default ===
|
|
||||||
sqlite3.oo1.OpfsSAHPool[sahPoolConfig.name])
|
|
||||||
.assert(sqlite3.capi.sqlite3_js_vfs_list().indexOf(sahPoolConfig.name) >= 0);
|
|
||||||
|
|
||||||
T.assert(0 === u1.getFileCount());
|
|
||||||
const DbCtor = sqlite3.oo1.OpfsSAHPool.default;
|
|
||||||
const dbName = '/foo.db';
|
|
||||||
let db = new DbCtor(dbName);
|
|
||||||
T.assert(1 === u1.getFileCount());
|
|
||||||
db.exec([
|
|
||||||
'create table t(a);',
|
|
||||||
'insert into t(a) values(1),(2),(3)'
|
|
||||||
]);
|
|
||||||
T.assert(1 === u1.getFileCount());
|
|
||||||
T.assert(3 === db.selectValue('select count(*) from t'));
|
|
||||||
db.close();
|
|
||||||
T.assert(1 === u1.getFileCount());
|
|
||||||
db = new DbCtor(dbName);
|
|
||||||
T.assert(1 === u1.getFileCount());
|
|
||||||
db.close();
|
|
||||||
T.assert(1 === u1.getFileCount())
|
|
||||||
.assert(true === u1.unlink(dbName))
|
|
||||||
.assert(false === u1.unlink(dbName))
|
|
||||||
.assert(0 === u1.getFileCount());
|
|
||||||
|
|
||||||
T.assert(true === await u2.removeVfs())
|
|
||||||
.assert(false === await u1.removeVfs())
|
|
||||||
.assert(!sqlite3.capi.sqlite3_vfs_find(sahPoolConfig.name));
|
|
||||||
|
|
||||||
let cErr, u3;
|
|
||||||
const conf2 = JSON.parse(JSON.stringify(sahPoolConfig));
|
|
||||||
conf2.$testThrowInInit = new Error("Testing throwing during init.");
|
|
||||||
conf2.name = sahPoolConfig.name+'-err';
|
|
||||||
const P3 = await inst(conf2).then(u=>u3 = u).catch((e)=>cErr=e);
|
|
||||||
T.assert(P3 === conf2.$testThrowInInit)
|
|
||||||
.assert(cErr === P3)
|
|
||||||
.assert(undefined === u3)
|
|
||||||
.assert(!sqlite3.capi.sqlite3_vfs_find(conf2.name));
|
|
||||||
}
|
|
||||||
}/*OPFS SAH Pool sanity checks*/)
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
T.g('Hook APIs')
|
T.g('Hook APIs')
|
||||||
.t({
|
.t({
|
||||||
@ -3096,6 +2903,200 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
|||||||
}
|
}
|
||||||
})/*session API sanity tests*/
|
})/*session API sanity tests*/
|
||||||
;/*end of session API group*/;
|
;/*end of session API group*/;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
T.g('OPFS: Origin-Private File System',
|
||||||
|
(sqlite3)=>(sqlite3.capi.sqlite3_vfs_find("opfs")
|
||||||
|
|| 'requires "opfs" VFS'))
|
||||||
|
.t({
|
||||||
|
name: 'OPFS db sanity checks',
|
||||||
|
test: async function(sqlite3){
|
||||||
|
const filename = this.opfsDbFile = 'sqlite3-tester1.db';
|
||||||
|
const pVfs = this.opfsVfs = capi.sqlite3_vfs_find('opfs');
|
||||||
|
T.assert(pVfs);
|
||||||
|
const unlink = this.opfsUnlink =
|
||||||
|
(fn=filename)=>{wasm.sqlite3_wasm_vfs_unlink(pVfs,fn)};
|
||||||
|
unlink();
|
||||||
|
let db = new sqlite3.oo1.OpfsDb(filename);
|
||||||
|
try {
|
||||||
|
db.exec([
|
||||||
|
'create table p(a);',
|
||||||
|
'insert into p(a) values(1),(2),(3)'
|
||||||
|
]);
|
||||||
|
T.assert(3 === db.selectValue('select count(*) from p'));
|
||||||
|
db.close();
|
||||||
|
db = new sqlite3.oo1.OpfsDb(filename);
|
||||||
|
db.exec('insert into p(a) values(4),(5),(6)');
|
||||||
|
T.assert(6 === db.selectValue('select count(*) from p'));
|
||||||
|
this.opfsDbExport = capi.sqlite3_js_db_export(db);
|
||||||
|
T.assert(this.opfsDbExport instanceof Uint8Array)
|
||||||
|
.assert(this.opfsDbExport.byteLength>0
|
||||||
|
&& 0===this.opfsDbExport.byteLength % 512);
|
||||||
|
}finally{
|
||||||
|
db.close();
|
||||||
|
unlink();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}/*OPFS db sanity checks*/)
|
||||||
|
.t({
|
||||||
|
name: 'OPFS export/import',
|
||||||
|
test: async function(sqlite3){
|
||||||
|
let db;
|
||||||
|
try {
|
||||||
|
const exp = this.opfsDbExport;
|
||||||
|
delete this.opfsDbExport;
|
||||||
|
capi.sqlite3_js_vfs_create_file("opfs", this.opfsDbFile, exp);
|
||||||
|
const db = new sqlite3.oo1.OpfsDb(this.opfsDbFile);
|
||||||
|
T.assert(6 === db.selectValue('select count(*) from p'));
|
||||||
|
}finally{
|
||||||
|
if(db) db.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}/*OPFS export/import*/)
|
||||||
|
.t({
|
||||||
|
name: 'OPFS utility APIs and sqlite3_js_vfs_create_file()',
|
||||||
|
test: async function(sqlite3){
|
||||||
|
const filename = this.opfsDbFile;
|
||||||
|
const pVfs = this.opfsVfs;
|
||||||
|
const unlink = this.opfsUnlink;
|
||||||
|
T.assert(filename && pVfs && !!unlink);
|
||||||
|
delete this.opfsDbFile;
|
||||||
|
delete this.opfsVfs;
|
||||||
|
delete this.opfsUnlink;
|
||||||
|
unlink();
|
||||||
|
// Sanity-test sqlite3_js_vfs_create_file()...
|
||||||
|
/**************************************************************
|
||||||
|
ATTENTION CLIENT-SIDE USERS: sqlite3.opfs is NOT intended
|
||||||
|
for client-side use. It is only for this project's own
|
||||||
|
internal use. Its APIs are subject to change or removal at
|
||||||
|
any time.
|
||||||
|
***************************************************************/
|
||||||
|
const opfs = sqlite3.opfs;
|
||||||
|
const fSize = 1379;
|
||||||
|
let sh;
|
||||||
|
try{
|
||||||
|
T.assert(!(await opfs.entryExists(filename)));
|
||||||
|
capi.sqlite3_js_vfs_create_file(
|
||||||
|
pVfs, filename, null, fSize
|
||||||
|
);
|
||||||
|
T.assert(await opfs.entryExists(filename));
|
||||||
|
let fh = await opfs.rootDirectory.getFileHandle(filename);
|
||||||
|
sh = await fh.createSyncAccessHandle();
|
||||||
|
T.assert(fSize === await sh.getSize());
|
||||||
|
await sh.close();
|
||||||
|
sh = undefined;
|
||||||
|
unlink();
|
||||||
|
T.assert(!(await opfs.entryExists(filename)));
|
||||||
|
|
||||||
|
const ba = new Uint8Array([1,2,3,4,5]);
|
||||||
|
capi.sqlite3_js_vfs_create_file(
|
||||||
|
"opfs", filename, ba
|
||||||
|
);
|
||||||
|
T.assert(await opfs.entryExists(filename));
|
||||||
|
fh = await opfs.rootDirectory.getFileHandle(filename);
|
||||||
|
sh = await fh.createSyncAccessHandle();
|
||||||
|
T.assert(ba.byteLength === await sh.getSize());
|
||||||
|
await sh.close();
|
||||||
|
sh = undefined;
|
||||||
|
unlink();
|
||||||
|
|
||||||
|
T.mustThrowMatching(()=>{
|
||||||
|
capi.sqlite3_js_vfs_create_file(
|
||||||
|
"no-such-vfs", filename, ba
|
||||||
|
);
|
||||||
|
}, "SQLITE_NOTFOUND: Unknown sqlite3_vfs name: no-such-vfs");
|
||||||
|
}finally{
|
||||||
|
if(sh) await sh.close();
|
||||||
|
unlink();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some sanity checks of the opfs utility functions...
|
||||||
|
const testDir = '/sqlite3-opfs-'+opfs.randomFilename(12);
|
||||||
|
const aDir = testDir+'/test/dir';
|
||||||
|
T.assert(await opfs.mkdir(aDir), "mkdir failed")
|
||||||
|
.assert(await opfs.mkdir(aDir), "mkdir must pass if the dir exists")
|
||||||
|
.assert(!(await opfs.unlink(testDir+'/test')), "delete 1 should have failed (dir not empty)")
|
||||||
|
.assert((await opfs.unlink(testDir+'/test/dir')), "delete 2 failed")
|
||||||
|
.assert(!(await opfs.unlink(testDir+'/test/dir')),
|
||||||
|
"delete 2b should have failed (dir already deleted)")
|
||||||
|
.assert((await opfs.unlink(testDir, true)), "delete 3 failed")
|
||||||
|
.assert(!(await opfs.entryExists(testDir)),
|
||||||
|
"entryExists(",testDir,") should have failed");
|
||||||
|
}
|
||||||
|
}/*OPFS util sanity checks*/)
|
||||||
|
;/* end OPFS tests */
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
T.g('OPFS SyncAccessHandle Pool VFS',
|
||||||
|
(sqlite3)=>(hasOpfs() || "requires OPFS APIs"))
|
||||||
|
.t({
|
||||||
|
name: 'SAH sanity checks',
|
||||||
|
test: async function(sqlite3){
|
||||||
|
T.assert(!sqlite3.capi.sqlite3_vfs_find(sahPoolConfig.name))
|
||||||
|
.assert(sqlite3.capi.sqlite3_js_vfs_list().indexOf(sahPoolConfig.name) < 0)
|
||||||
|
const inst = sqlite3.installOpfsSAHPoolVfs,
|
||||||
|
catcher = (e)=>{
|
||||||
|
error("Cannot load SAH pool VFS.",
|
||||||
|
"This might not be a problem,",
|
||||||
|
"depending on the environment.");
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let u1, u2;
|
||||||
|
const P1 = inst(sahPoolConfig).then(u=>u1 = u).catch(catcher),
|
||||||
|
P2 = inst(sahPoolConfig).then(u=>u2 = u).catch(catcher);
|
||||||
|
await Promise.all([P1, P2]);
|
||||||
|
if(!P1) return;
|
||||||
|
T.assert(u1 === u2)
|
||||||
|
.assert(sahPoolConfig.name === u1.vfsName)
|
||||||
|
.assert(sqlite3.capi.sqlite3_vfs_find(sahPoolConfig.name))
|
||||||
|
.assert(u1.getCapacity() >= sahPoolConfig.initialCapacity
|
||||||
|
/* If a test fails before we get to nuke the VFS, we
|
||||||
|
can have more than the initial capacity on the next
|
||||||
|
run. */)
|
||||||
|
.assert(u1.getCapacity() + 2 === (await u2.addCapacity(2)))
|
||||||
|
.assert(2 === (await u2.reduceCapacity(2)))
|
||||||
|
.assert(sqlite3.oo1.OpfsSAHPool.default instanceof Function)
|
||||||
|
.assert(sqlite3.oo1.OpfsSAHPool.default ===
|
||||||
|
sqlite3.oo1.OpfsSAHPool[sahPoolConfig.name])
|
||||||
|
.assert(sqlite3.capi.sqlite3_js_vfs_list().indexOf(sahPoolConfig.name) >= 0);
|
||||||
|
|
||||||
|
T.assert(0 === u1.getFileCount());
|
||||||
|
const DbCtor = sqlite3.oo1.OpfsSAHPool.default;
|
||||||
|
const dbName = '/foo.db';
|
||||||
|
let db = new DbCtor(dbName);
|
||||||
|
T.assert(1 === u1.getFileCount());
|
||||||
|
db.exec([
|
||||||
|
'create table t(a);',
|
||||||
|
'insert into t(a) values(1),(2),(3)'
|
||||||
|
]);
|
||||||
|
T.assert(1 === u1.getFileCount());
|
||||||
|
T.assert(3 === db.selectValue('select count(*) from t'));
|
||||||
|
db.close();
|
||||||
|
T.assert(1 === u1.getFileCount());
|
||||||
|
db = new DbCtor(dbName);
|
||||||
|
T.assert(1 === u1.getFileCount());
|
||||||
|
db.close();
|
||||||
|
T.assert(1 === u1.getFileCount())
|
||||||
|
.assert(true === u1.unlink(dbName))
|
||||||
|
.assert(false === u1.unlink(dbName))
|
||||||
|
.assert(0 === u1.getFileCount());
|
||||||
|
|
||||||
|
T.assert(true === await u2.removeVfs())
|
||||||
|
.assert(false === await u1.removeVfs())
|
||||||
|
.assert(!sqlite3.capi.sqlite3_vfs_find(sahPoolConfig.name));
|
||||||
|
|
||||||
|
let cErr, u3;
|
||||||
|
const conf2 = JSON.parse(JSON.stringify(sahPoolConfig));
|
||||||
|
conf2.$testThrowInInit = new Error("Testing throwing during init.");
|
||||||
|
conf2.name = sahPoolConfig.name+'-err';
|
||||||
|
const P3 = await inst(conf2).then(u=>u3 = u).catch((e)=>cErr=e);
|
||||||
|
T.assert(P3 === conf2.$testThrowInInit)
|
||||||
|
.assert(cErr === P3)
|
||||||
|
.assert(undefined === u3)
|
||||||
|
.assert(!sqlite3.capi.sqlite3_vfs_find(conf2.name));
|
||||||
|
}
|
||||||
|
}/*OPFS SAH Pool sanity checks*/)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
T.g('Bug Reports')
|
T.g('Bug Reports')
|
||||||
.t({
|
.t({
|
||||||
|
16
manifest
16
manifest
@ -1,5 +1,5 @@
|
|||||||
C More\sopfs-sahpool\stests.
|
C Internal\srefactoring\sin\sopfs-sahpool.\sMove\sOPFS\stests\sto\sthe\send\sof\stester1.c-cpp.js.
|
||||||
D 2023-07-18T19:47:19.982
|
D 2023-07-19T08:18:25.901
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
@ -501,8 +501,8 @@ F ext/wasm/api/sqlite3-api-prologue.js d747cbb379e13881c9edf39dce019cbbbae860c45
|
|||||||
F ext/wasm/api/sqlite3-api-worker1.js 9f32af64df1a031071912eea7a201557fe39b1738645c0134562bb84e88e2fec
|
F ext/wasm/api/sqlite3-api-worker1.js 9f32af64df1a031071912eea7a201557fe39b1738645c0134562bb84e88e2fec
|
||||||
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
||||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379
|
F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379
|
||||||
F ext/wasm/api/sqlite3-v-helper.js fc9ed95433d943a65905d16b7ed51515ddb6667d2a2c5a711c7ce33b29d3be31
|
F ext/wasm/api/sqlite3-v-helper.js e4b7b27a8259e40407b3c16e42dd5df05b80726c609594cc23b1565dc2ad9ca2
|
||||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.js a33b88beb55e0e19a8f9c3d37620e9aa58a0a32cacf7c398195d3d045d414815
|
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.js 9a8ba44b775b0e8faaffc8d877cfef0726713c2ca368e5776b59d9029f5ebf23
|
||||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 4946af0d6fbd395aa39966562ca85900664605a5f0cc10fff50146dee527812c
|
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 4946af0d6fbd395aa39966562ca85900664605a5f0cc10fff50146dee527812c
|
||||||
F ext/wasm/api/sqlite3-wasm.c 8867f1d41c112fb4a2cfe22ff224eccaf309fcdea266cee0ec554f85db72ef0f
|
F ext/wasm/api/sqlite3-wasm.c 8867f1d41c112fb4a2cfe22ff224eccaf309fcdea266cee0ec554f85db72ef0f
|
||||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f
|
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f
|
||||||
@ -549,7 +549,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
|
|||||||
F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b
|
F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b
|
||||||
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
|
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
|
||||||
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
|
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
|
||||||
F ext/wasm/tester1.c-pp.js f625ce01681956cfd895a834d8aeb68d59595200441628ac2e41adf48788d8c9
|
F ext/wasm/tester1.c-pp.js a72fc43950ce26c1ad7cee47aa225dd18efdb92743cf616b2e114b4cd1cdf2dd
|
||||||
F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1
|
F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1
|
||||||
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
|
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
|
||||||
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
|
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
|
||||||
@ -2044,8 +2044,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 9c8a73aff0f291e0c18072372e0d8961d3a05910489598d0d342227d99871954
|
P 60713fa9c4627ef17e0b8778eee37913d2b930c5a06414721a00af30e1395090
|
||||||
R 17462841136511130de69ca7a00ea9cc
|
R b81da7c28422da4e0ac61aef8c2566f8
|
||||||
U stephan
|
U stephan
|
||||||
Z c3c355ff206bb421832084a0cbc9cd73
|
Z 2d92190e2a732ef23d4b23ca479d2da6
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@ -1 +1 @@
|
|||||||
60713fa9c4627ef17e0b8778eee37913d2b930c5a06414721a00af30e1395090
|
6bd5a7413dd830ca41b587a2826fb599a2196fb0186646a2333500f950b3cf4d
|
Reference in New Issue
Block a user