assert Fossil.cx
scope { /* Some generic test code... */
const FI = Fossil.file
assert FI.isAccessible(__FILE)
assert !FI.isAccessible(__FILE + '.nope')
assert [FI.isFile __FILE]
assert ![FI.isFile __FILE + '.baz']
assert 0 < [FI.size __FILE]
[print "This script's name: " __FILE ' ==canonical==> ' [FI.canonicalName __FILE]]
//[print __SRC ': mtime of this script: ' [strftime '%c' [FI.mtime __FILE]]]
var repoDb = ARGV.flags.r
const f = Fossil.createContext()
if(repoDb){
[print __SRC ': Repo db: ' f.db.repo]
}
assert f inherits Fossil.Context
[print __SRC ': f=' f ', f.db=' f.db ]
//[api.ob.push]
if(1 && f.db){
var list = array['repo', 'checkout']
const n = [list.length]
for{var k, db, fname, i = 0}{i<n}{i+=1}{
k = list.(i)
db = f.db.(k)
db || continue
[print __SRC ": Db details:"]
fname = db.filename
[print "\tDb type: " k]
[print "\tDB file: " fname]
[print '\tSize:\t' [FI.size fname]]
[print '\tmtime:\t' [strftime '%c' [FI.mtime fname]]]
}
if(f.db.checkout){
var x = $f.selectVal {
SELECT value FROM vvar WHERE name='repository'
}
$print 'selectVal = ' x
assert 'string' === typename x
x = $f.selectVal {SELECT value FROM vvar WHERE 0}
//$print 'selectVal = ' x
assert undefined === x
x = $f.selectVal {SELECT NULL}
//$print 'selectVal = ' x
assert null === x
}
}
//[api.ob.pop]
assert f.db
assert 'Db' === typename f.db
if(f.db.repo){
var uuid = [f.symToUuid 'trunk']
assert 'string'===typename uuid
assert 40 === [uuid.length]
var rid = [f.symToRid 'trunk']
assert 'integer'===typename rid
assert rid > 0
$print "Repo trunk: " uuid " (RID " rid ")"
unset uuid, rid
assert 'undefined' === typename rid
assert 'undefined' === typename uuid
catch {
$print "Stash entries:" f.selectVal
[f.dumpQuery
{SELECT stashid AS stashid,
vid AS vid,
datetime(ctime) AS ctime,
comment AS comment
FROM stash
ORDER BY stashid DESC
}
undefined // bind parameter(s, array)
'\t' // record separator
]
} /* ignore error - stash doesn't exist until used. */
}
/**
(Former) bug reminder: if we take a reference to
one of the native db handles and then use
it after closing the native db handle
via [f.closeRepo] or [f.closeCheckout]
then the handle holds a stale native pointer.
We can fix this using cwal_weak_ref, but
so far it's not worth the effort. As long as
we just let the handle lie, and don't call any
bound native methods, this is okay, but calling
methods will have undefined results.
hackhackhack... the binding now simply invalidates
those handles then closeRepo/Checkout() are called.
*/
var unlinked = f.db.repo
if(0) {
[f.closeRepo]
assert !f.db.repo
assert 'exception' === typename catch{[f.closeRepo]}
}else if(1){
$f.closeCheckout
assert !f.db.repo
assert !f.db.checkout
assert 'exception' === typename catch{[f.closeRepo]}
assert 'exception' === typename catch{[f.closeCheckout]}
}
if(!f.db.repo){
// see comments above
assert Fossil.rc.TYPE === catch{[unlinked.exec "SELECT 1"]}.code
}
/**
[f.openDb ...] works slightly differently than
[Fossil.openDb]. If a FossilContext is the 'this' of
an openDb() call then the db connection gets the array
of fossil-specific DB functions installed and it may
(depending on how it's called) require that the db
be a valid repo. The "extra features" include that the
db will use the Fossil Context's traceSql setting.
*/
/**
openMode is a string which describes how to open/interpret a db file.
The string can contain any of the characters 'r', 'w', 'c', 'v'.
The default access mode is 'rwc' (largely for historical
reasons). If the string contains 'w', write mode is added, and
'c' means "create if not exists"
and implies 'w'. The 'v' flag means to verify that the db is
a repository. This validation currently only works when the db
is opened via Context.openDb(), not Fossil.openDb() (they are
the same function, they just interpret the 'this' argument
differently).
*/
var openMode = 'c'
var db = [f.openDb
//":memory:"
__FILE+'.db'
openMode
]
[print __SRC ': db=' db ' ==> ' db.filename]
var ex = catch {
[db.execMulti {
BEGIN;
DROP TABLE IF EXISTS t;
CREATE TABLE t(a,b);
COMMIT;
}]
var st = [db.prepare "INSERT INTO t (a,b) VALUES (?,?)"]
[print __SRC ": Prepared statement: " st]
assert 2 === st.parameterCount
assert 0 === st.columnCount
var buf = [api.Buffer 5]
[buf.append 'bbb']
[st.bind 1 'aaa']
[st.bind 2 buf]
[st.step]
[st.reset]
if(0){
const FI = Fossil.file
[buf.capacity [FI.size __FILE] + 2]
[buf.length 0]
[buf.readFile __FILE]
var sz = [buf.length]
assert sz > 0
[buf.compress]
[st.bind array['ccc',buf]]
}else{
[st.bind array['ccc','ddd']]
}
unset buf
[st.step]
[st.finalize]
assert Fossil.rc.TYPE === catch{[st.finalize]}.code
st = [db.prepare "SELECT a a,b b FROM t WHERE ? ORDER BY ROWID"]
assert 2 === st.columnCount
assert 1 === st.parameterCount
assert 2 === [st.columnNames.length]
[st.bind 1 1]
assert [st.step]
assert 'aaa' === [st.get 0]
var b = [st.get 1]
('buffer'===typename b) && (b = [b.toString])
assert 'bbb' === b
[st.reset]
var a = [st.stepArray]
assert 'array' === typename a
assert 'aaa' === a.0
b = a.1
('buffer'===typename b) && (b = [b.toString])
assert 'bbb' === b
[st.reset]
var o = [st.stepObject]
assert 'object' === typename o
assert 'aaa' === o.a
b = o.b
('buffer'===typename b) && (b = [b.toString])
assert 'bbb' === b
[st.finalize]
}
ex && throw ex//[print __SRC ": EXCEPTION:" ex]
const stringify = proc(v){
var b = [api.Buffer]
[b.appendf '%1$J' v]
return [b.toString]
}
var list = array[]
db.each(object{
sql: {SELECT a a, b b FROM t WHERE ?},
bind: true,
mode: 1, //1==array (default), 0==object
callback:proc(){
assert 2 === [columnNames.length]
assert 'a' === columnNames.0
assert 'b' === columnNames.1
assert rowNumber > 0
/** BUG: when this callback is a string,
the script name is unknown in assertion trace
and exceptions here, and line/col are relative to
this callback string. This is because that level
of script bindings doesn't have the call location
info and the script engine cannot figure it out
because of how src locations/script names are
figured out on demand. Not sure how to fix that
(needs to be done (or enabled) at the th1ish
level).
*/
/* __SRC is also (of course) wrong here if callback
is-a String/Buffer.
*/
list.push(clone(this))
$print __SRC ': row #' rowNumber '=' this
}
})
$print 'Collected results:' list
[db.close]
assert Fossil.rc.TYPE === catch{[db.close]}.code
//[f.finalize] // optional (or let GC take care of it at end of scope)
}
1 && scope {
// Holy cow, zlib is a memory hog: it mallocs 64k
// for each de/compression op.
const FI = Fossil.file
var b = api.Buffer(FI.size(__FILE) + 2)
$b.readFile __FILE
assert b inherits api.prototypes.Buffer
var sz = [b.length]
assert sz > 0
[b.compress]
var szC = [b.length]
assert szC < sz
print("Compressed buffer: ",sz," ==> ",szC)
var zFile = __FILE+'.z';
[b.writeToFile zFile]
print("Compressed copy written to ",zFile);
assert szC === [FI.size zFile]
[b.uncompress]
assert sz === [b.length]
print("Decompressed buffer: ",szC," ==> ",sz)
//print(b.toString())
}
1 && scope {
var b = api.Buffer(30)
$b.append {abcdefghijklm}
var bb = clone(b)
assert bb.length() === b.length()
assert bb === b
assert 0 === b.compare(bb)
for {var i = 0, sz=bb.length()}{i<sz}{i+=1}{
assert b.byteAt(i) === bb.byteAt(i)
}
bb.append("hi")
assert b.compare(bb) < 0
assert bb.compare(b) > 0
assert bb !== b
assert bb != b
}