$print {
/**
Running hash table tests...
*/
}
const each = proc {k,v} {
//assert ! [this.mayIterate] // fixme: why does this _not_ fail?
$print ' ' this '\t' typename k k '\t=\t' typename v v
//$print 'this =' this this.search this.insert
if(!argv.callee.checked){
argv.callee.checked =
assert 306 === catch{$this.insert "MUST FAIL" true}.code
$print "Modification during iteration properly failed."
}
}
0 && scope {
// check valgrind...
const h [api.Hash 10000]
assert 'hash' === typename h
}
1 && scope {
$print "Hashtable #1..."
const h = [api.Hash 19];
assert [h.mayIterate]
//$print 'h =' h h.insert h.search
[h.insert "foo" "bar"]
assert [h.containsEntry "foo"]
assert ![h.containsEntry "bar"]
[h.insert "foo" "baz"]
h.foo = "the other foo"
$print 'get foo =' [h.search "foo"]
assert "the other foo" === h.foo
assert "baz" === [h.search "foo"]
$print h "table entries:"
$h.eachEntry each
assert 'function' === typename h.prototype.entryKeys
assert 'function' === typename h.prototype.prototype.propertyKeys
assert h.prototype.prototype.propertyKeys !== h.entryKeys
var pk = h.prototype.prototype.propertyKeys
assert 'function' === typename pk.apply
var pkeys = [pk.apply h]
$print 'pk.apply... ' pkeys
assert "the other foo" === h.(pkeys.0)
$print "ending scope"
}
0 && scope {
$print "Hashtable #2..."
var h;
scope {
h = [api.Hash 400];
assert (400 < [h.hashSize]) && (600 > [h.hashSize])
[h.insert "foo" "bar"]
[h.insert "foot" "baz"]
$print h "table entries:"
[h.eachEntry each]
[h.remove "foo"]
[h.remove "foot"]
$print "hash =" h
}
$print "ending scope" h
}
1 && scope {
$print "Hashtable #N..."
const h = [api.Hash 19];
assert 1 === refcount h
if(false){
[[[h.insert "1" "one"].
insert 1 "!"].
insert h h] /* ugly, huh? */
}else{
[h.insert "1" "one"]
[h.insert 1 "!"]
[h.insert h h]
}
assert 3 === refcount h
assert 3 === [h.entryCount]
[h.eachEntry each]
var keys = [h.entryKeys], vals = [h.entryValues]
assert 'array' === typename keys
assert 3 === [keys.length]
assert 'array' === typename vals
assert 3 === [vals.length]
assert vals.1 === [h.search keys.1]
$print h "table entries:"
[h.eachEntry each]
assert "one" === [h.search "1"]
assert "!" === [h.search 1]
const oldRc = refcount h
[h.remove h]
assert (oldRc-2) === refcount h
assert 2 === [h.entryCount]
$print "Hash table properties again:"
[h.eachEntry each]
keys = [h.entryKeys]
vals = [h.entryValues]
$print 'keys =' keys
$print 'values =' vals
assert 2 === [keys.length]
assert 2 === [vals.length]
[h.clearEntries]
assert 0 === [h.entryCount]
//$print "Hash table properties after clearing:"
//[h.eachEntry each]
//$print "(should be empty)"
}
1 && scope {
const obj object { a: 3, b: 5 }
const h [api.Hash]
$print "Hashtable #X..." h
h.cpProp = proc{from}{
const self = this
$from.eachProperty proc{k,v}{
[self.insert k v]
}
}
[h.cpProp obj]
assert 2 === [h.entryCount]
assert [h.entryValues].1 === obj.([h.entryKeys].1)
//$print "Copied properties:"
//[h.eachEntry each]
[h.insert 'a' 7]
assert 2 === [h.entryCount]
//$print "Modified copied properties:"
//[h.eachEntry each]
assert [h.search 'a'] !== obj.a
}
0 && scope {
// check valgrind...
const h [api.Hash 1000]
assert 'hash' === typename h
assert 1000 <= [h.hashSize]
}
$print "done"
return "hoorah for hashes!"