4 The author disclaims copyright to this source code. In place of a
5 legal notice, here is a blessing:
7 * May you do good and not evil.
8 * May you find forgiveness for yourself and forgive others.
9 * May you share freely, never taking more than you give.
11 ***********************************************************************
13 This file contains bootstrapping code used by various test scripts
14 which live in this file's directory.
18 /* querySelectorAll() proxy */
19 const EAll = function(/*[element=document,] cssSelector*/){
20 return (arguments
.length
>1 ? arguments
[0] : document
)
21 .querySelectorAll(arguments
[arguments
.length
-1]);
23 /* querySelector() proxy */
24 const E = function(/*[element=document,] cssSelector*/){
25 return (arguments
.length
>1 ? arguments
[0] : document
)
26 .querySelector(arguments
[arguments
.length
-1]);
30 Helpers for writing sqlite3-specific tests.
32 self
.SqliteTestUtil
= {
33 /** Running total of the number of tests run via
37 If expr is a function, it is called and its result
38 is returned, coerced to a bool, else expr, coerced to
41 toBool: function(expr
){
42 return (expr
instanceof Function
) ? !!expr() : !!expr
;
44 /** abort() if expr is false. If expr is a function, it
45 is called and its result is evaluated.
47 assert
: function f(expr
, msg
){
49 f
._
= ('undefined'===typeof abort
50 ? (msg
)=>{throw new Error(msg
)}
54 if(!this.toBool(expr
)){
55 f
._(msg
|| "Assertion failed.");
59 /** Identical to assert() but throws instead of calling
61 affirm: function(expr
, msg
){
63 if(!this.toBool(expr
)) throw new Error(msg
|| "Affirmation failed.");
66 /** Calls f() and squelches any exception it throws. If it
67 does not throw, this function throws. */
68 mustThrow: function(f
, msg
){
71 try{ f(); } catch(e
){err
=e
;}
72 if(!err
) throw new Error(msg
|| "Expected exception.");
76 Works like mustThrow() but expects filter to be a regex,
77 function, or string to match/filter the resulting exception
78 against. If f() does not throw, this test fails and an Error is
79 thrown. If filter is a regex, the test passes if
80 filter.test(error.message) passes. If it's a function, the test
81 passes if filter(error) returns truthy. If it's a string, the
82 test passes if the filter matches the exception message
83 precisely. In all other cases the test fails, throwing an
86 If it throws, msg is used as the error report unless it's falsy,
87 in which case a default is used.
89 mustThrowMatching: function(f
, filter
, msg
){
92 try{ f(); } catch(e
){err
=e
;}
93 if(!err
) throw new Error(msg
|| "Expected exception.");
95 if(filter
instanceof RegExp
) pass
= filter
.test(err
.message
);
96 else if(filter
instanceof Function
) pass
= filter(err
);
97 else if('string' === typeof filter
) pass
= (err
.message
=== filter
);
99 throw new Error(msg
|| ("Filter rejected this exception: "+err
.message
));
103 /** Throws if expr is truthy or expr is a function and expr()
105 throwIf: function(expr
, msg
){
107 if(this.toBool(expr
)) throw new Error(msg
|| "throwIf() failed");
110 /** Throws if expr is falsy or expr is a function and expr()
112 throwUnless: function(expr
, msg
){
114 if(!this.toBool(expr
)) throw new Error(msg
|| "throwUnless() failed");
119 Parses window.location.search-style string into an object
120 containing key/value pairs of URL arguments (already
121 urldecoded). The object is created using Object.create(null),
122 so contains only parsed-out properties and has no prototype
123 (and thus no inherited properties).
125 If the str argument is not passed (arguments.length==0) then
126 window.location.search.substring(1) is used by default. If
127 neither str is passed in nor window exists then false is returned.
129 On success it returns an Object containing the key/value pairs
130 parsed from the string. Keys which have no value are treated
131 has having the boolean true value.
133 Pedantic licensing note: this code has appeared in other source
134 trees, but was originally written by the same person who pasted
137 processUrlArgs: function(str
) {
138 if( 0 === arguments
.length
) {
139 if( ('undefined' === typeof window
) ||
141 !window
.location
.search
) return false;
142 else str
= (''+window
.location
.search
).substring(1);
144 if( ! str
) return false;
145 str
= (''+str
).split(/#/,2)[0]; // remove
#... to avoid it being added as part
of the last value
.
146 const args
= Object
.create(null);
147 const sp
= str
.split(/&+/);
148 const rx
= /^([^=]+)(=(.+))?/;
151 m
= rx
.exec( sp
[i
] );
153 args
[decodeURIComponent(m
[1])] = (m
[3] ? decodeURIComponent(m
[3]) : true);
160 This is a module object for use with the emscripten-installed
161 sqlite3InitModule() factory function.
163 self
.sqlite3TestModule
= {
165 Array of functions to call after Emscripten has initialized the
166 wasm module. Each gets passed the Emscripten module object
167 (which is _this_ object).
170 /* function(theModule){...} */
172 //onRuntimeInitialized: function(){},
173 /* Proxy for C-side stdout output. */
174 print
: (...args
)=>{console
.log(...args
)},
175 /* Proxy for C-side stderr output. */
176 printErr
: (...args
)=>{console
.error(...args
)},
178 Called by the Emscripten module init bits to report loading
179 progress. It gets passed an empty argument when loading is done
180 (after onRuntimeInitialized() and any this.postRun callbacks
183 setStatus
: function f(text
){
185 f
.last
= { text
: '', step
: 0 };
187 status
: E('#module-status'),
188 progress
: E('#module-progress'),
189 spinner
: E('#module-spinner')
192 if(text
=== f
.last
.text
) return;
195 f
.ui
.progress
.value
= f
.last
.step
;
196 f
.ui
.progress
.max
= f
.last
.step
+ 1;
200 f
.ui
.status
.classList
.remove('hidden');
201 f
.ui
.status
.innerText
= text
;
204 f
.ui
.progress
.remove();
205 f
.ui
.spinner
.remove();
206 delete f
.ui
.progress
;
209 f
.ui
.status
.classList
.add('hidden');
213 Config options used by the Emscripten-dependent initialization
214 which happens via this.initSqlite3(). This object gets
215 (indirectly) passed to sqlite3ApiBootstrap() to configure the
219 wasmfsOpfsDir
: "/opfs"
222 Intended to be called by apps which need to call the
223 Emscripten-installed sqlite3InitModule() routine. This function
224 temporarily installs this.sqlite3ApiConfig into the self
225 object, calls it sqlite3InitModule(), and removes
226 self.sqlite3ApiConfig after initialization is done. Returns the
227 promise from sqlite3InitModule(), and the next then() handler
228 will get the sqlite3 API object as its argument.
230 initSqlite3: function(){
231 self
.sqlite3ApiConfig
= this.sqlite3ApiConfig
;
232 return self
.sqlite3InitModule(this).finally(()=>delete self
.sqlite3ApiConfig
);
235 })(self
/*window or worker*/);