move tests to testament (#16101)
* move tests to testament * minor * fix random * disable test random
This commit is contained in:
parent
d306a04466
commit
cbc793b30b
56 changed files with 2205 additions and 2232 deletions
|
|
@ -665,36 +665,6 @@ proc prevPermutation*[T](x: var openArray[T]): bool {.discardable.} =
|
||||||
|
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
# Tests for lowerBound
|
|
||||||
var arr = @[1, 2, 3, 5, 6, 7, 8, 9]
|
|
||||||
assert arr.lowerBound(0) == 0
|
|
||||||
assert arr.lowerBound(4) == 3
|
|
||||||
assert arr.lowerBound(5) == 3
|
|
||||||
assert arr.lowerBound(10) == 8
|
|
||||||
arr = @[1, 5, 10]
|
|
||||||
assert arr.lowerBound(4) == 1
|
|
||||||
assert arr.lowerBound(5) == 1
|
|
||||||
assert arr.lowerBound(6) == 2
|
|
||||||
# Tests for isSorted
|
|
||||||
var srt1 = [1, 2, 3, 4, 4, 4, 4, 5]
|
|
||||||
var srt2 = ["iello", "hello"]
|
|
||||||
var srt3 = [1.0, 1.0, 1.0]
|
|
||||||
var srt4: seq[int]
|
|
||||||
assert srt1.isSorted(cmp) == true
|
|
||||||
assert srt2.isSorted(cmp) == false
|
|
||||||
assert srt3.isSorted(cmp) == true
|
|
||||||
assert srt4.isSorted(cmp) == true
|
|
||||||
var srtseq = newSeq[int]()
|
|
||||||
assert srtseq.isSorted(cmp) == true
|
|
||||||
# Tests for reversed
|
|
||||||
var arr1 = @[0, 1, 2, 3, 4]
|
|
||||||
assert arr1.reversed() == @[4, 3, 2, 1, 0]
|
|
||||||
for i in 0 .. high(arr1):
|
|
||||||
assert arr1.reversed(0, i) == arr1.reversed()[high(arr1) - i .. high(arr1)]
|
|
||||||
assert arr1.reversed(i, high(arr1)) == arr1.reversed()[0 .. high(arr1) - i]
|
|
||||||
|
|
||||||
|
|
||||||
proc rotateInternal[T](arg: var openArray[T]; first, middle, last: int): int =
|
proc rotateInternal[T](arg: var openArray[T]; first, middle, last: int): int =
|
||||||
## A port of std::rotate from c++. Ported from `this reference <http://www.cplusplus.com/reference/algorithm/rotate/>`_.
|
## A port of std::rotate from c++. Ported from `this reference <http://www.cplusplus.com/reference/algorithm/rotate/>`_.
|
||||||
result = first + last - middle
|
result = first + last - middle
|
||||||
|
|
@ -852,71 +822,3 @@ proc rotatedLeft*[T](arg: openArray[T]; dist: int): seq[T] =
|
||||||
let arglen = arg.len
|
let arglen = arg.len
|
||||||
let distLeft = ((dist mod arglen) + arglen) mod arglen
|
let distLeft = ((dist mod arglen) + arglen) mod arglen
|
||||||
arg.rotatedInternal(0, distLeft, arg.len)
|
arg.rotatedInternal(0, distLeft, arg.len)
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
var list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
|
||||||
let list2 = list.rotatedLeft(1 ..< 9, 3)
|
|
||||||
let expected = [0, 4, 5, 6, 7, 8, 1, 2, 3, 9, 10]
|
|
||||||
|
|
||||||
doAssert list.rotateLeft(1 ..< 9, 3) == 6
|
|
||||||
doAssert list == expected
|
|
||||||
doAssert list2 == @expected
|
|
||||||
|
|
||||||
var s0, s1, s2, s3, s4, s5 = "xxxabcdefgxxx"
|
|
||||||
|
|
||||||
doAssert s0.rotateLeft(3 ..< 10, 3) == 7
|
|
||||||
doAssert s0 == "xxxdefgabcxxx"
|
|
||||||
doAssert s1.rotateLeft(3 ..< 10, 2) == 8
|
|
||||||
doAssert s1 == "xxxcdefgabxxx"
|
|
||||||
doAssert s2.rotateLeft(3 ..< 10, 4) == 6
|
|
||||||
doAssert s2 == "xxxefgabcdxxx"
|
|
||||||
doAssert s3.rotateLeft(3 ..< 10, -3) == 6
|
|
||||||
doAssert s3 == "xxxefgabcdxxx"
|
|
||||||
doAssert s4.rotateLeft(3 ..< 10, -10) == 6
|
|
||||||
doAssert s4 == "xxxefgabcdxxx"
|
|
||||||
doAssert s5.rotateLeft(3 ..< 10, 11) == 6
|
|
||||||
doAssert s5 == "xxxefgabcdxxx"
|
|
||||||
|
|
||||||
block product:
|
|
||||||
doAssert product(newSeq[seq[int]]()) == newSeq[seq[int]](), "empty input"
|
|
||||||
doAssert product(@[newSeq[int](), @[], @[]]) == newSeq[seq[int]](), "bit more empty input"
|
|
||||||
doAssert product(@[@[1, 2]]) == @[@[1, 2]], "a simple case of one element"
|
|
||||||
doAssert product(@[@[1, 2], @[3, 4]]) == @[@[2, 4], @[1, 4], @[2, 3], @[1,
|
|
||||||
3]], "two elements"
|
|
||||||
doAssert product(@[@[1, 2], @[3, 4], @[5, 6]]) == @[@[2, 4, 6], @[1, 4, 6],
|
|
||||||
@[2, 3, 6], @[1, 3, 6], @[2, 4, 5], @[1, 4, 5], @[2, 3, 5], @[1, 3, 5]], "three elements"
|
|
||||||
doAssert product(@[@[1, 2], @[]]) == newSeq[seq[int]](), "two elements, but one empty"
|
|
||||||
|
|
||||||
block lowerBound:
|
|
||||||
doAssert lowerBound([1, 2, 4], 3, system.cmp[int]) == 2
|
|
||||||
doAssert lowerBound([1, 2, 2, 3], 4, system.cmp[int]) == 4
|
|
||||||
doAssert lowerBound([1, 2, 3, 10], 11) == 4
|
|
||||||
|
|
||||||
block upperBound:
|
|
||||||
doAssert upperBound([1, 2, 4], 3, system.cmp[int]) == 2
|
|
||||||
doAssert upperBound([1, 2, 2, 3], 3, system.cmp[int]) == 4
|
|
||||||
doAssert upperBound([1, 2, 3, 5], 3) == 3
|
|
||||||
|
|
||||||
block fillEmptySeq:
|
|
||||||
var s = newSeq[int]()
|
|
||||||
s.fill(0)
|
|
||||||
|
|
||||||
block testBinarySearch:
|
|
||||||
var noData: seq[int]
|
|
||||||
doAssert binarySearch(noData, 7) == -1
|
|
||||||
let oneData = @[1]
|
|
||||||
doAssert binarySearch(oneData, 1) == 0
|
|
||||||
doAssert binarySearch(onedata, 7) == -1
|
|
||||||
let someData = @[1, 3, 4, 7]
|
|
||||||
doAssert binarySearch(someData, 1) == 0
|
|
||||||
doAssert binarySearch(somedata, 7) == 3
|
|
||||||
doAssert binarySearch(someData, -1) == -1
|
|
||||||
doAssert binarySearch(someData, 5) == -1
|
|
||||||
doAssert binarySearch(someData, 13) == -1
|
|
||||||
let moreData = @[1, 3, 5, 7, 4711]
|
|
||||||
doAssert binarySearch(moreData, -1) == -1
|
|
||||||
doAssert binarySearch(moreData, 1) == 0
|
|
||||||
doAssert binarySearch(moreData, 5) == 2
|
|
||||||
doAssert binarySearch(moreData, 6) == -1
|
|
||||||
doAssert binarySearch(moreData, 4711) == 4
|
|
||||||
doAssert binarySearch(moreData, 4712) == -1
|
|
||||||
|
|
|
||||||
|
|
@ -567,66 +567,3 @@ runnableExamples:
|
||||||
doAssert critbitAsDict["key"] == -int.high
|
doAssert critbitAsDict["key"] == -int.high
|
||||||
critbitAsDict["key"] = int.high
|
critbitAsDict["key"] = int.high
|
||||||
doAssert critbitAsDict["key"] == int.high
|
doAssert critbitAsDict["key"] == int.high
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
import sequtils
|
|
||||||
|
|
||||||
var r: CritBitTree[void]
|
|
||||||
r.incl "abc"
|
|
||||||
r.incl "xyz"
|
|
||||||
r.incl "def"
|
|
||||||
r.incl "definition"
|
|
||||||
r.incl "prefix"
|
|
||||||
r.incl "foo"
|
|
||||||
|
|
||||||
doAssert r.contains"def"
|
|
||||||
|
|
||||||
r.excl "def"
|
|
||||||
assert r.missingOrExcl("foo") == false
|
|
||||||
assert "foo" notin toSeq(r.items)
|
|
||||||
|
|
||||||
assert r.missingOrExcl("foo") == true
|
|
||||||
|
|
||||||
assert toSeq(r.items) == @["abc", "definition", "prefix", "xyz"]
|
|
||||||
|
|
||||||
assert toSeq(r.itemsWithPrefix("de")) == @["definition"]
|
|
||||||
var c = CritBitTree[int]()
|
|
||||||
|
|
||||||
c.inc("a")
|
|
||||||
assert c["a"] == 1
|
|
||||||
|
|
||||||
c.inc("a", 4)
|
|
||||||
assert c["a"] == 5
|
|
||||||
|
|
||||||
c.inc("a", -5)
|
|
||||||
assert c["a"] == 0
|
|
||||||
|
|
||||||
c.inc("b", 2)
|
|
||||||
assert c["b"] == 2
|
|
||||||
|
|
||||||
c.inc("c", 3)
|
|
||||||
assert c["c"] == 3
|
|
||||||
|
|
||||||
c.inc("a", 1)
|
|
||||||
assert c["a"] == 1
|
|
||||||
|
|
||||||
var cf = CritBitTree[float]()
|
|
||||||
|
|
||||||
cf.incl("a", 1.0)
|
|
||||||
assert cf["a"] == 1.0
|
|
||||||
|
|
||||||
cf.incl("b", 2.0)
|
|
||||||
assert cf["b"] == 2.0
|
|
||||||
|
|
||||||
cf.incl("c", 3.0)
|
|
||||||
assert cf["c"] == 3.0
|
|
||||||
|
|
||||||
assert cf.len == 3
|
|
||||||
cf.excl("c")
|
|
||||||
assert cf.len == 2
|
|
||||||
|
|
||||||
var cb: CritBitTree[string]
|
|
||||||
cb.incl("help", "help")
|
|
||||||
for k in cb.keysWithPrefix("helpp"):
|
|
||||||
doAssert false, "there is no prefix helpp"
|
|
||||||
|
|
|
||||||
|
|
@ -2873,317 +2873,3 @@ iterator mvalues*[A](t: CountTableRef[A]): var int =
|
||||||
if t.data[h].val != 0:
|
if t.data[h].val != 0:
|
||||||
yield t.data[h].val
|
yield t.data[h].val
|
||||||
assert(len(t) == L, "the length of the table changed while iterating over it")
|
assert(len(t) == L, "the length of the table changed while iterating over it")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
type
|
|
||||||
Person = object
|
|
||||||
firstName, lastName: string
|
|
||||||
|
|
||||||
proc hash(x: Person): Hash =
|
|
||||||
## Piggyback on the already available string hash proc.
|
|
||||||
##
|
|
||||||
## Without this proc nothing works!
|
|
||||||
result = x.firstName.hash !& x.lastName.hash
|
|
||||||
result = !$result
|
|
||||||
|
|
||||||
var
|
|
||||||
salaries = initTable[Person, int]()
|
|
||||||
p1, p2: Person
|
|
||||||
p1.firstName = "Jon"
|
|
||||||
p1.lastName = "Ross"
|
|
||||||
salaries[p1] = 30_000
|
|
||||||
p2.firstName = "소진"
|
|
||||||
p2.lastName = "박"
|
|
||||||
salaries[p2] = 45_000
|
|
||||||
var
|
|
||||||
s2 = initOrderedTable[Person, int]()
|
|
||||||
s3 = initCountTable[Person]()
|
|
||||||
s2[p1] = 30_000
|
|
||||||
s2[p2] = 45_000
|
|
||||||
s3[p1] = 30_000
|
|
||||||
s3[p2] = 45_000
|
|
||||||
|
|
||||||
block: # Ordered table should preserve order after deletion
|
|
||||||
var
|
|
||||||
s4 = initOrderedTable[int, int]()
|
|
||||||
s4[1] = 1
|
|
||||||
s4[2] = 2
|
|
||||||
s4[3] = 3
|
|
||||||
|
|
||||||
var prev = 0
|
|
||||||
for i in s4.values:
|
|
||||||
doAssert(prev < i)
|
|
||||||
prev = i
|
|
||||||
|
|
||||||
s4.del(2)
|
|
||||||
doAssert(2 notin s4)
|
|
||||||
doAssert(s4.len == 2)
|
|
||||||
prev = 0
|
|
||||||
for i in s4.values:
|
|
||||||
doAssert(prev < i)
|
|
||||||
prev = i
|
|
||||||
|
|
||||||
block: # Deletion from OrderedTable should account for collision groups. See issue #5057.
|
|
||||||
# The bug is reproducible only with exact keys
|
|
||||||
const key1 = "boy_jackpot.inGamma"
|
|
||||||
const key2 = "boy_jackpot.outBlack"
|
|
||||||
|
|
||||||
var t = {
|
|
||||||
key1: 0,
|
|
||||||
key2: 0
|
|
||||||
}.toOrderedTable()
|
|
||||||
|
|
||||||
t.del(key1)
|
|
||||||
assert(t.len == 1)
|
|
||||||
assert(key2 in t)
|
|
||||||
|
|
||||||
var
|
|
||||||
t1 = initCountTable[string]()
|
|
||||||
t2 = initCountTable[string]()
|
|
||||||
t1.inc("foo")
|
|
||||||
t1.inc("bar", 2)
|
|
||||||
t1.inc("baz", 3)
|
|
||||||
t2.inc("foo", 4)
|
|
||||||
t2.inc("bar")
|
|
||||||
t2.inc("baz", 11)
|
|
||||||
merge(t1, t2)
|
|
||||||
assert(t1["foo"] == 5)
|
|
||||||
assert(t1["bar"] == 3)
|
|
||||||
assert(t1["baz"] == 14)
|
|
||||||
|
|
||||||
let
|
|
||||||
t1r = newCountTable[string]()
|
|
||||||
t2r = newCountTable[string]()
|
|
||||||
t1r.inc("foo")
|
|
||||||
t1r.inc("bar", 2)
|
|
||||||
t1r.inc("baz", 3)
|
|
||||||
t2r.inc("foo", 4)
|
|
||||||
t2r.inc("bar")
|
|
||||||
t2r.inc("baz", 11)
|
|
||||||
merge(t1r, t2r)
|
|
||||||
assert(t1r["foo"] == 5)
|
|
||||||
assert(t1r["bar"] == 3)
|
|
||||||
assert(t1r["baz"] == 14)
|
|
||||||
|
|
||||||
var
|
|
||||||
t1l = initCountTable[string]()
|
|
||||||
t2l = initCountTable[string]()
|
|
||||||
t1l.inc("foo")
|
|
||||||
t1l.inc("bar", 2)
|
|
||||||
t1l.inc("baz", 3)
|
|
||||||
t2l.inc("foo", 4)
|
|
||||||
t2l.inc("bar")
|
|
||||||
t2l.inc("baz", 11)
|
|
||||||
|
|
||||||
block:
|
|
||||||
const testKey = "TESTKEY"
|
|
||||||
let t: CountTableRef[string] = newCountTable[string]()
|
|
||||||
|
|
||||||
# Before, does not compile with error message:
|
|
||||||
#test_counttable.nim(7, 43) template/generic instantiation from here
|
|
||||||
#lib/pure/collections/tables.nim(117, 21) template/generic instantiation from here
|
|
||||||
#lib/pure/collections/tableimpl.nim(32, 27) Error: undeclared field: 'hcode
|
|
||||||
doAssert 0 == t[testKey]
|
|
||||||
t.inc(testKey, 3)
|
|
||||||
doAssert 3 == t[testKey]
|
|
||||||
|
|
||||||
block:
|
|
||||||
# Clear tests
|
|
||||||
var clearTable = newTable[int, string]()
|
|
||||||
clearTable[42] = "asd"
|
|
||||||
clearTable[123123] = "piuyqwb "
|
|
||||||
doAssert clearTable[42] == "asd"
|
|
||||||
clearTable.clear()
|
|
||||||
doAssert(not clearTable.hasKey(123123))
|
|
||||||
doAssert clearTable.getOrDefault(42) == ""
|
|
||||||
|
|
||||||
block: #5482
|
|
||||||
var a = [("wrong?", "foo"), ("wrong?", "foo2")].newOrderedTable()
|
|
||||||
var b = newOrderedTable[string, string](initialSize = 2)
|
|
||||||
b["wrong?"] = "foo"
|
|
||||||
b["wrong?"] = "foo2"
|
|
||||||
assert a == b
|
|
||||||
|
|
||||||
block: #5482
|
|
||||||
var a = {"wrong?": "foo", "wrong?": "foo2"}.newOrderedTable()
|
|
||||||
var b = newOrderedTable[string, string](initialSize = 2)
|
|
||||||
b["wrong?"] = "foo"
|
|
||||||
b["wrong?"] = "foo2"
|
|
||||||
assert a == b
|
|
||||||
|
|
||||||
block: #5487
|
|
||||||
var a = {"wrong?": "foo", "wrong?": "foo2"}.newOrderedTable()
|
|
||||||
var b = newOrderedTable[string, string]() # notice, default size!
|
|
||||||
b["wrong?"] = "foo"
|
|
||||||
b["wrong?"] = "foo2"
|
|
||||||
assert a == b
|
|
||||||
|
|
||||||
block: #5487
|
|
||||||
var a = [("wrong?", "foo"), ("wrong?", "foo2")].newOrderedTable()
|
|
||||||
var b = newOrderedTable[string, string]() # notice, default size!
|
|
||||||
b["wrong?"] = "foo"
|
|
||||||
b["wrong?"] = "foo2"
|
|
||||||
assert a == b
|
|
||||||
|
|
||||||
block:
|
|
||||||
var a = {"wrong?": "foo", "wrong?": "foo2"}.newOrderedTable()
|
|
||||||
var b = [("wrong?", "foo"), ("wrong?", "foo2")].newOrderedTable()
|
|
||||||
var c = newOrderedTable[string, string]() # notice, default size!
|
|
||||||
c["wrong?"] = "foo"
|
|
||||||
c["wrong?"] = "foo2"
|
|
||||||
assert a == b
|
|
||||||
assert a == c
|
|
||||||
|
|
||||||
block: #6250
|
|
||||||
let
|
|
||||||
a = {3: 1}.toOrderedTable
|
|
||||||
b = {3: 2}.toOrderedTable
|
|
||||||
assert((a == b) == false)
|
|
||||||
assert((b == a) == false)
|
|
||||||
|
|
||||||
block: #6250
|
|
||||||
let
|
|
||||||
a = {3: 2}.toOrderedTable
|
|
||||||
b = {3: 2}.toOrderedTable
|
|
||||||
assert((a == b) == true)
|
|
||||||
assert((b == a) == true)
|
|
||||||
|
|
||||||
block: # CountTable.smallest
|
|
||||||
let t = toCountTable([0, 0, 5, 5, 5])
|
|
||||||
doAssert t.smallest == (0, 2)
|
|
||||||
|
|
||||||
block: #10065
|
|
||||||
let t = toCountTable("abracadabra")
|
|
||||||
doAssert t['z'] == 0
|
|
||||||
|
|
||||||
var t_mut = toCountTable("abracadabra")
|
|
||||||
doAssert t_mut['z'] == 0
|
|
||||||
# the previous read may not have modified the table.
|
|
||||||
doAssert t_mut.hasKey('z') == false
|
|
||||||
t_mut['z'] = 1
|
|
||||||
doAssert t_mut['z'] == 1
|
|
||||||
doAssert t_mut.hasKey('z') == true
|
|
||||||
|
|
||||||
block: #12813 #13079
|
|
||||||
var t = toCountTable("abracadabra")
|
|
||||||
doAssert len(t) == 5
|
|
||||||
|
|
||||||
t['a'] = 0 # remove a key
|
|
||||||
doAssert len(t) == 4
|
|
||||||
|
|
||||||
block:
|
|
||||||
var tp: Table[string, string] = initTable[string, string]()
|
|
||||||
doAssert "test1" == tp.getOrDefault("test1", "test1")
|
|
||||||
tp["test2"] = "test2"
|
|
||||||
doAssert "test2" == tp.getOrDefault("test2", "test1")
|
|
||||||
var tr: TableRef[string, string] = newTable[string, string]()
|
|
||||||
doAssert "test1" == tr.getOrDefault("test1", "test1")
|
|
||||||
tr["test2"] = "test2"
|
|
||||||
doAssert "test2" == tr.getOrDefault("test2", "test1")
|
|
||||||
var op: OrderedTable[string, string] = initOrderedTable[string, string]()
|
|
||||||
doAssert "test1" == op.getOrDefault("test1", "test1")
|
|
||||||
op["test2"] = "test2"
|
|
||||||
doAssert "test2" == op.getOrDefault("test2", "test1")
|
|
||||||
var orf: OrderedTableRef[string, string] = newOrderedTable[string, string]()
|
|
||||||
doAssert "test1" == orf.getOrDefault("test1", "test1")
|
|
||||||
orf["test2"] = "test2"
|
|
||||||
doAssert "test2" == orf.getOrDefault("test2", "test1")
|
|
||||||
|
|
||||||
block tableWithoutInit:
|
|
||||||
var
|
|
||||||
a: Table[string, int]
|
|
||||||
b: Table[string, int]
|
|
||||||
c: Table[string, int]
|
|
||||||
d: Table[string, int]
|
|
||||||
e: Table[string, int]
|
|
||||||
|
|
||||||
a["a"] = 7
|
|
||||||
doAssert a.hasKey("a")
|
|
||||||
doAssert a.len == 1
|
|
||||||
doAssert a["a"] == 7
|
|
||||||
a["a"] = 9
|
|
||||||
doAssert a.len == 1
|
|
||||||
doAssert a["a"] == 9
|
|
||||||
|
|
||||||
doAssert b.hasKeyOrPut("b", 5) == false
|
|
||||||
doAssert b.hasKey("b")
|
|
||||||
doAssert b.hasKeyOrPut("b", 8)
|
|
||||||
doAssert b["b"] == 5
|
|
||||||
|
|
||||||
doAssert c.getOrDefault("a") == 0
|
|
||||||
doAssert c.getOrDefault("a", 3) == 3
|
|
||||||
c["a"] = 6
|
|
||||||
doAssert c.getOrDefault("a", 3) == 6
|
|
||||||
|
|
||||||
doAssert d.mgetOrPut("a", 3) == 3
|
|
||||||
doAssert d.mgetOrPut("a", 6) == 3
|
|
||||||
|
|
||||||
var x = 99
|
|
||||||
doAssert e.pop("a", x) == false
|
|
||||||
doAssert x == 99
|
|
||||||
e["a"] = 77
|
|
||||||
doAssert e.pop("a", x)
|
|
||||||
doAssert x == 77
|
|
||||||
|
|
||||||
block orderedTableWithoutInit:
|
|
||||||
var
|
|
||||||
a: OrderedTable[string, int]
|
|
||||||
b: OrderedTable[string, int]
|
|
||||||
c: OrderedTable[string, int]
|
|
||||||
d: OrderedTable[string, int]
|
|
||||||
|
|
||||||
a["a"] = 7
|
|
||||||
doAssert a.hasKey("a")
|
|
||||||
doAssert a.len == 1
|
|
||||||
doAssert a["a"] == 7
|
|
||||||
a["a"] = 9
|
|
||||||
doAssert a.len == 1
|
|
||||||
doAssert a["a"] == 9
|
|
||||||
|
|
||||||
doAssert b.hasKeyOrPut("b", 5) == false
|
|
||||||
doAssert b.hasKey("b")
|
|
||||||
doAssert b.hasKeyOrPut("b", 8)
|
|
||||||
doAssert b["b"] == 5
|
|
||||||
|
|
||||||
doAssert c.getOrDefault("a") == 0
|
|
||||||
doAssert c.getOrDefault("a", 3) == 3
|
|
||||||
c["a"] = 6
|
|
||||||
doAssert c.getOrDefault("a", 3) == 6
|
|
||||||
|
|
||||||
doAssert d.mgetOrPut("a", 3) == 3
|
|
||||||
doAssert d.mgetOrPut("a", 6) == 3
|
|
||||||
|
|
||||||
block countTableWithoutInit:
|
|
||||||
var
|
|
||||||
a: CountTable[string]
|
|
||||||
b: CountTable[string]
|
|
||||||
c: CountTable[string]
|
|
||||||
d: CountTable[string]
|
|
||||||
e: CountTable[string]
|
|
||||||
|
|
||||||
a["a"] = 7
|
|
||||||
doAssert a.hasKey("a")
|
|
||||||
doAssert a.len == 1
|
|
||||||
doAssert a["a"] == 7
|
|
||||||
a["a"] = 9
|
|
||||||
doAssert a.len == 1
|
|
||||||
doAssert a["a"] == 9
|
|
||||||
|
|
||||||
doAssert b["b"] == 0
|
|
||||||
b.inc("b")
|
|
||||||
doAssert b["b"] == 1
|
|
||||||
|
|
||||||
doAssert c.getOrDefault("a") == 0
|
|
||||||
doAssert c.getOrDefault("a", 3) == 3
|
|
||||||
c["a"] = 6
|
|
||||||
doAssert c.getOrDefault("a", 3) == 6
|
|
||||||
|
|
||||||
e["f"] = 3
|
|
||||||
merge(d, e)
|
|
||||||
doAssert d.hasKey("f")
|
|
||||||
d.inc("f")
|
|
||||||
merge(d, e)
|
|
||||||
doAssert d["f"] == 7
|
|
||||||
|
|
|
||||||
|
|
@ -59,18 +59,3 @@ proc setCookie*(key, value: string, expires: DateTime|Time,
|
||||||
return setCookie(key, value, domain, path,
|
return setCookie(key, value, domain, path,
|
||||||
format(expires.utc, "ddd',' dd MMM yyyy HH:mm:ss 'GMT'"),
|
format(expires.utc, "ddd',' dd MMM yyyy HH:mm:ss 'GMT'"),
|
||||||
noname, secure, httpOnly)
|
noname, secure, httpOnly)
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
let expire = fromUnix(0) + 1.seconds
|
|
||||||
|
|
||||||
let cookies = [
|
|
||||||
setCookie("test", "value", expire),
|
|
||||||
setCookie("test", "value", expire.local),
|
|
||||||
setCookie("test", "value", expire.utc)
|
|
||||||
]
|
|
||||||
let expected = "Set-Cookie: test=value; Expires=Thu, 01 Jan 1970 00:00:01 GMT"
|
|
||||||
doAssert cookies == [expected, expected, expected]
|
|
||||||
|
|
||||||
let table = parseCookies("uid=1; kp=2")
|
|
||||||
doAssert table["uid"] == "1"
|
|
||||||
doAssert table["kp"] == "2"
|
|
||||||
|
|
|
||||||
|
|
@ -178,11 +178,3 @@ template maximumPositiveValue*(T: typedesc[float64]): float64 = DBL_MAX
|
||||||
template epsilon*(T: typedesc[float64]): float64 = DBL_EPSILON
|
template epsilon*(T: typedesc[float64]): float64 = DBL_EPSILON
|
||||||
## The difference between 1.0 and the smallest number greater than
|
## The difference between 1.0 and the smallest number greater than
|
||||||
## 1.0 that can be represented in a 64-bit floating-point type.
|
## 1.0 that can be represented in a 64-bit floating-point type.
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
func is_significant(x: float): bool =
|
|
||||||
if x > minimumPositiveValue(float) and x < maximumPositiveValue(float): true
|
|
||||||
else: false
|
|
||||||
|
|
||||||
doAssert is_significant(10.0)
|
|
||||||
|
|
|
||||||
|
|
@ -485,46 +485,3 @@ proc hash*[A](x: set[A]): Hash =
|
||||||
for it in items(x):
|
for it in items(x):
|
||||||
result = result !& hash(it)
|
result = result !& hash(it)
|
||||||
result = !$result
|
result = !$result
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
block empty:
|
|
||||||
var
|
|
||||||
a = ""
|
|
||||||
b = newSeq[char]()
|
|
||||||
c = newSeq[int]()
|
|
||||||
d = cstring""
|
|
||||||
e = "abcd"
|
|
||||||
doAssert hash(a) == 0
|
|
||||||
doAssert hash(b) == 0
|
|
||||||
doAssert hash(c) == 0
|
|
||||||
doAssert hash(d) == 0
|
|
||||||
doAssert hashIgnoreCase(a) == 0
|
|
||||||
doAssert hashIgnoreStyle(a) == 0
|
|
||||||
doAssert hash(e, 3, 2) == 0
|
|
||||||
block sameButDifferent:
|
|
||||||
doAssert hash("aa bb aaaa1234") == hash("aa bb aaaa1234", 0, 13)
|
|
||||||
doAssert hash("aa bb aaaa1234") == hash(cstring"aa bb aaaa1234")
|
|
||||||
doAssert hashIgnoreCase("aA bb aAAa1234") == hashIgnoreCase("aa bb aaaa1234")
|
|
||||||
doAssert hashIgnoreStyle("aa_bb_AAaa1234") == hashIgnoreCase("aaBBAAAa1234")
|
|
||||||
block smallSize: # no multibyte hashing
|
|
||||||
let
|
|
||||||
xx = @['H', 'i']
|
|
||||||
ii = @[72'u8, 105]
|
|
||||||
ss = "Hi"
|
|
||||||
doAssert hash(xx) == hash(ii)
|
|
||||||
doAssert hash(xx) == hash(ss)
|
|
||||||
doAssert hash(xx) == hash(xx, 0, xx.high)
|
|
||||||
doAssert hash(ss) == hash(ss, 0, ss.high)
|
|
||||||
block largeSize: # longer than 4 characters
|
|
||||||
let
|
|
||||||
xx = @['H', 'e', 'l', 'l', 'o']
|
|
||||||
xxl = @['H', 'e', 'l', 'l', 'o', 'w', 'e', 'e', 'n', 's']
|
|
||||||
ssl = "Helloweens"
|
|
||||||
doAssert hash(xxl) == hash(ssl)
|
|
||||||
doAssert hash(xxl) == hash(xxl, 0, xxl.high)
|
|
||||||
doAssert hash(ssl) == hash(ssl, 0, ssl.high)
|
|
||||||
doAssert hash(xx) == hash(xxl, 0, 4)
|
|
||||||
doAssert hash(xx) == hash(ssl, 0, 4)
|
|
||||||
doAssert hash(xx, 0, 3) == hash(xxl, 0, 3)
|
|
||||||
doAssert hash(xx, 0, 3) == hash(ssl, 0, 3)
|
|
||||||
|
|
|
||||||
|
|
@ -345,28 +345,3 @@ func is5xx*(code: HttpCode): bool {.inline.} =
|
||||||
|
|
||||||
func `$`*(httpMethod: HttpMethod): string =
|
func `$`*(httpMethod: HttpMethod): string =
|
||||||
return (system.`$`(httpMethod))[4 .. ^1].toUpperAscii()
|
return (system.`$`(httpMethod))[4 .. ^1].toUpperAscii()
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
var test = newHttpHeaders()
|
|
||||||
test["Connection"] = @["Upgrade", "Close"]
|
|
||||||
doAssert test["Connection", 0] == "Upgrade"
|
|
||||||
doAssert test["Connection", 1] == "Close"
|
|
||||||
test.add("Connection", "Test")
|
|
||||||
doAssert test["Connection", 2] == "Test"
|
|
||||||
doAssert "upgrade" in test["Connection"]
|
|
||||||
|
|
||||||
# Bug #5344.
|
|
||||||
doAssert parseHeader("foobar: ") == ("foobar", @[""])
|
|
||||||
let (key, value) = parseHeader("foobar: ")
|
|
||||||
test = newHttpHeaders()
|
|
||||||
test[key] = value
|
|
||||||
doAssert test["foobar"] == ""
|
|
||||||
|
|
||||||
doAssert parseHeader("foobar:") == ("foobar", @[""])
|
|
||||||
|
|
||||||
block: # test title case
|
|
||||||
var testTitleCase = newHttpHeaders(titleCase=true)
|
|
||||||
testTitleCase.add("content-length", "1")
|
|
||||||
doAssert testTitleCase.hasKey("Content-Length")
|
|
||||||
for key, val in testTitleCase:
|
|
||||||
doAssert key == "Content-Length"
|
|
||||||
|
|
|
||||||
|
|
@ -1101,128 +1101,3 @@ proc lcm*[T](x: openArray[T]): T {.since: (1, 1).} =
|
||||||
while i < x.len:
|
while i < x.len:
|
||||||
result = lcm(result, x[i])
|
result = lcm(result, x[i])
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
||||||
when isMainModule and not defined(js) and not windowsCC89:
|
|
||||||
# Check for no side effect annotation
|
|
||||||
proc mySqrt(num: float): float {.noSideEffect.} =
|
|
||||||
return sqrt(num)
|
|
||||||
|
|
||||||
# check gamma function
|
|
||||||
assert(gamma(5.0) == 24.0) # 4!
|
|
||||||
assert(lgamma(1.0) == 0.0) # ln(1.0) == 0.0
|
|
||||||
assert(erf(6.0) > erf(5.0))
|
|
||||||
assert(erfc(6.0) < erfc(5.0))
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
# Function for approximate comparison of floats
|
|
||||||
proc `==~`(x, y: float): bool = (abs(x-y) < 1e-9)
|
|
||||||
|
|
||||||
block: # prod
|
|
||||||
doAssert prod([1, 2, 3, 4]) == 24
|
|
||||||
doAssert prod([1.5, 3.4]) == 5.1
|
|
||||||
let x: seq[float] = @[]
|
|
||||||
doAssert prod(x) == 1.0
|
|
||||||
|
|
||||||
block: # round() tests
|
|
||||||
# Round to 0 decimal places
|
|
||||||
doAssert round(54.652) ==~ 55.0
|
|
||||||
doAssert round(54.352) ==~ 54.0
|
|
||||||
doAssert round(-54.652) ==~ -55.0
|
|
||||||
doAssert round(-54.352) ==~ -54.0
|
|
||||||
doAssert round(0.0) ==~ 0.0
|
|
||||||
|
|
||||||
block: # splitDecimal() tests
|
|
||||||
doAssert splitDecimal(54.674).intpart ==~ 54.0
|
|
||||||
doAssert splitDecimal(54.674).floatpart ==~ 0.674
|
|
||||||
doAssert splitDecimal(-693.4356).intpart ==~ -693.0
|
|
||||||
doAssert splitDecimal(-693.4356).floatpart ==~ -0.4356
|
|
||||||
doAssert splitDecimal(0.0).intpart ==~ 0.0
|
|
||||||
doAssert splitDecimal(0.0).floatpart ==~ 0.0
|
|
||||||
|
|
||||||
block: # trunc tests for vcc
|
|
||||||
doAssert(trunc(-1.1) == -1)
|
|
||||||
doAssert(trunc(1.1) == 1)
|
|
||||||
doAssert(trunc(-0.1) == -0)
|
|
||||||
doAssert(trunc(0.1) == 0)
|
|
||||||
|
|
||||||
#special case
|
|
||||||
doAssert(classify(trunc(1e1000000)) == fcInf)
|
|
||||||
doAssert(classify(trunc(-1e1000000)) == fcNegInf)
|
|
||||||
doAssert(classify(trunc(0.0/0.0)) == fcNan)
|
|
||||||
doAssert(classify(trunc(0.0)) == fcZero)
|
|
||||||
|
|
||||||
#trick the compiler to produce signed zero
|
|
||||||
let
|
|
||||||
f_neg_one = -1.0
|
|
||||||
f_zero = 0.0
|
|
||||||
f_nan = f_zero / f_zero
|
|
||||||
|
|
||||||
doAssert(classify(trunc(f_neg_one*f_zero)) == fcNegZero)
|
|
||||||
|
|
||||||
doAssert(trunc(-1.1'f32) == -1)
|
|
||||||
doAssert(trunc(1.1'f32) == 1)
|
|
||||||
doAssert(trunc(-0.1'f32) == -0)
|
|
||||||
doAssert(trunc(0.1'f32) == 0)
|
|
||||||
doAssert(classify(trunc(1e1000000'f32)) == fcInf)
|
|
||||||
doAssert(classify(trunc(-1e1000000'f32)) == fcNegInf)
|
|
||||||
doAssert(classify(trunc(f_nan.float32)) == fcNan)
|
|
||||||
doAssert(classify(trunc(0.0'f32)) == fcZero)
|
|
||||||
|
|
||||||
block: # sgn() tests
|
|
||||||
assert sgn(1'i8) == 1
|
|
||||||
assert sgn(1'i16) == 1
|
|
||||||
assert sgn(1'i32) == 1
|
|
||||||
assert sgn(1'i64) == 1
|
|
||||||
assert sgn(1'u8) == 1
|
|
||||||
assert sgn(1'u16) == 1
|
|
||||||
assert sgn(1'u32) == 1
|
|
||||||
assert sgn(1'u64) == 1
|
|
||||||
assert sgn(-12342.8844'f32) == -1
|
|
||||||
assert sgn(123.9834'f64) == 1
|
|
||||||
assert sgn(0'i32) == 0
|
|
||||||
assert sgn(0'f32) == 0
|
|
||||||
assert sgn(NegInf) == -1
|
|
||||||
assert sgn(Inf) == 1
|
|
||||||
assert sgn(NaN) == 0
|
|
||||||
|
|
||||||
block: # fac() tests
|
|
||||||
try:
|
|
||||||
discard fac(-1)
|
|
||||||
except AssertionDefect:
|
|
||||||
discard
|
|
||||||
|
|
||||||
doAssert fac(0) == 1
|
|
||||||
doAssert fac(1) == 1
|
|
||||||
doAssert fac(2) == 2
|
|
||||||
doAssert fac(3) == 6
|
|
||||||
doAssert fac(4) == 24
|
|
||||||
|
|
||||||
block: # floorMod/floorDiv
|
|
||||||
doAssert floorDiv(8, 3) == 2
|
|
||||||
doAssert floorMod(8, 3) == 2
|
|
||||||
|
|
||||||
doAssert floorDiv(8, -3) == -3
|
|
||||||
doAssert floorMod(8, -3) == -1
|
|
||||||
|
|
||||||
doAssert floorDiv(-8, 3) == -3
|
|
||||||
doAssert floorMod(-8, 3) == 1
|
|
||||||
|
|
||||||
doAssert floorDiv(-8, -3) == 2
|
|
||||||
doAssert floorMod(-8, -3) == -2
|
|
||||||
|
|
||||||
doAssert floorMod(8.0, -3.0) ==~ -1.0
|
|
||||||
doAssert floorMod(-8.5, 3.0) ==~ 0.5
|
|
||||||
|
|
||||||
block: # log
|
|
||||||
doAssert log(4.0, 3.0) ==~ ln(4.0) / ln(3.0)
|
|
||||||
doAssert log2(8.0'f64) == 3.0'f64
|
|
||||||
doAssert log2(4.0'f64) == 2.0'f64
|
|
||||||
doAssert log2(2.0'f64) == 1.0'f64
|
|
||||||
doAssert log2(1.0'f64) == 0.0'f64
|
|
||||||
doAssert classify(log2(0.0'f64)) == fcNegInf
|
|
||||||
|
|
||||||
doAssert log2(8.0'f32) == 3.0'f32
|
|
||||||
doAssert log2(4.0'f32) == 2.0'f32
|
|
||||||
doAssert log2(2.0'f32) == 1.0'f32
|
|
||||||
doAssert log2(1.0'f32) == 0.0'f32
|
|
||||||
doAssert classify(log2(0.0'f32)) == fcNegInf
|
|
||||||
|
|
|
||||||
|
|
@ -278,12 +278,5 @@ proc md5Final*(c: var MD5Context, digest: var MD5Digest) =
|
||||||
zeroMem(addr(c), sizeof(MD5Context))
|
zeroMem(addr(c), sizeof(MD5Context))
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
assert(getMD5("Franz jagt im komplett verwahrlosten Taxi quer durch Bayern") ==
|
|
||||||
"a3cca2b2aa1e3b5b3b5aad99a8529074")
|
|
||||||
assert(getMD5("Frank jagt im komplett verwahrlosten Taxi quer durch Bayern") ==
|
|
||||||
"7e716d0e702df0505fc72e2b89467910")
|
|
||||||
assert($toMD5("") == "d41d8cd98f00b204e9800998ecf8427e")
|
|
||||||
|
|
||||||
when defined(nimHasStyleChecks):
|
when defined(nimHasStyleChecks):
|
||||||
{.pop.} #{.push styleChecks: off.}
|
{.pop.} #{.push styleChecks: off.}
|
||||||
|
|
|
||||||
|
|
@ -371,144 +371,3 @@ proc unsafeGet*[T](self: Option[T]): lent T {.inline.}=
|
||||||
## Generally, using `get proc <#get,Option[T]>`_ is preferred.
|
## Generally, using `get proc <#get,Option[T]>`_ is preferred.
|
||||||
assert self.isSome
|
assert self.isSome
|
||||||
result = self.val
|
result = self.val
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
import unittest, sequtils
|
|
||||||
|
|
||||||
# RefPerson is used to test that overloaded `==` operator is not called by
|
|
||||||
# options. It is defined here in the global scope, because otherwise the test
|
|
||||||
# will not even consider the `==` operator. Different bug?
|
|
||||||
type RefPerson = ref object
|
|
||||||
name: string
|
|
||||||
|
|
||||||
proc `==`(a, b: RefPerson): bool =
|
|
||||||
assert(not a.isNil and not b.isNil)
|
|
||||||
a.name == b.name
|
|
||||||
|
|
||||||
suite "options":
|
|
||||||
# work around a bug in unittest
|
|
||||||
let intNone = none(int)
|
|
||||||
let stringNone = none(string)
|
|
||||||
|
|
||||||
test "example":
|
|
||||||
proc find(haystack: string, needle: char): Option[int] =
|
|
||||||
for i, c in haystack:
|
|
||||||
if c == needle:
|
|
||||||
return some i
|
|
||||||
|
|
||||||
check("abc".find('c').get() == 2)
|
|
||||||
|
|
||||||
let result = "team".find('i')
|
|
||||||
|
|
||||||
check result == intNone
|
|
||||||
check result.isNone
|
|
||||||
|
|
||||||
test "some":
|
|
||||||
check some(6).get() == 6
|
|
||||||
check some("a").unsafeGet() == "a"
|
|
||||||
check some(6).isSome
|
|
||||||
check some("a").isSome
|
|
||||||
|
|
||||||
test "none":
|
|
||||||
expect UnpackDefect:
|
|
||||||
discard none(int).get()
|
|
||||||
check(none(int).isNone)
|
|
||||||
check(not none(string).isSome)
|
|
||||||
|
|
||||||
test "equality":
|
|
||||||
check some("a") == some("a")
|
|
||||||
check some(7) != some(6)
|
|
||||||
check some("a") != stringNone
|
|
||||||
check intNone == intNone
|
|
||||||
|
|
||||||
when compiles(some("a") == some(5)):
|
|
||||||
check false
|
|
||||||
when compiles(none(string) == none(int)):
|
|
||||||
check false
|
|
||||||
|
|
||||||
test "get with a default value":
|
|
||||||
check(some("Correct").get("Wrong") == "Correct")
|
|
||||||
check(stringNone.get("Correct") == "Correct")
|
|
||||||
|
|
||||||
test "$":
|
|
||||||
check($(some("Correct")) == "Some(\"Correct\")")
|
|
||||||
check($(stringNone) == "None[string]")
|
|
||||||
|
|
||||||
test "map with a void result":
|
|
||||||
var procRan = 0
|
|
||||||
some(123).map(proc (v: int) = procRan = v)
|
|
||||||
check procRan == 123
|
|
||||||
intNone.map(proc (v: int) = check false)
|
|
||||||
|
|
||||||
test "map":
|
|
||||||
check(some(123).map(proc (v: int): int = v * 2) == some(246))
|
|
||||||
check(intNone.map(proc (v: int): int = v * 2).isNone)
|
|
||||||
|
|
||||||
test "filter":
|
|
||||||
check(some(123).filter(proc (v: int): bool = v == 123) == some(123))
|
|
||||||
check(some(456).filter(proc (v: int): bool = v == 123).isNone)
|
|
||||||
check(intNone.filter(proc (v: int): bool = check false).isNone)
|
|
||||||
|
|
||||||
test "flatMap":
|
|
||||||
proc addOneIfNotZero(v: int): Option[int] =
|
|
||||||
if v != 0:
|
|
||||||
result = some(v + 1)
|
|
||||||
else:
|
|
||||||
result = none(int)
|
|
||||||
|
|
||||||
check(some(1).flatMap(addOneIfNotZero) == some(2))
|
|
||||||
check(some(0).flatMap(addOneIfNotZero) == none(int))
|
|
||||||
check(some(1).flatMap(addOneIfNotZero).flatMap(addOneIfNotZero) == some(3))
|
|
||||||
|
|
||||||
proc maybeToString(v: int): Option[string] =
|
|
||||||
if v != 0:
|
|
||||||
result = some($v)
|
|
||||||
else:
|
|
||||||
result = none(string)
|
|
||||||
|
|
||||||
check(some(1).flatMap(maybeToString) == some("1"))
|
|
||||||
|
|
||||||
proc maybeExclaim(v: string): Option[string] =
|
|
||||||
if v != "":
|
|
||||||
result = some v & "!"
|
|
||||||
else:
|
|
||||||
result = none(string)
|
|
||||||
|
|
||||||
check(some(1).flatMap(maybeToString).flatMap(maybeExclaim) == some("1!"))
|
|
||||||
check(some(0).flatMap(maybeToString).flatMap(maybeExclaim) == none(string))
|
|
||||||
|
|
||||||
test "SomePointer":
|
|
||||||
var intref: ref int
|
|
||||||
check(option(intref).isNone)
|
|
||||||
intref.new
|
|
||||||
check(option(intref).isSome)
|
|
||||||
|
|
||||||
let tmp = option(intref)
|
|
||||||
check(sizeof(tmp) == sizeof(ptr int))
|
|
||||||
|
|
||||||
var prc = proc (x: int): int = x + 1
|
|
||||||
check(option(prc).isSome)
|
|
||||||
prc = nil
|
|
||||||
check(option(prc).isNone)
|
|
||||||
|
|
||||||
test "none[T]":
|
|
||||||
check(none[int]().isNone)
|
|
||||||
check(none(int) == none[int]())
|
|
||||||
|
|
||||||
test "$ on typed with .name":
|
|
||||||
type Named = object
|
|
||||||
name: string
|
|
||||||
|
|
||||||
let nobody = none(Named)
|
|
||||||
check($nobody == "None[Named]")
|
|
||||||
|
|
||||||
test "$ on type with name()":
|
|
||||||
type Person = object
|
|
||||||
myname: string
|
|
||||||
|
|
||||||
let noperson = none(Person)
|
|
||||||
check($noperson == "None[Person]")
|
|
||||||
|
|
||||||
test "Ref type with overloaded `==`":
|
|
||||||
let p = some(RefPerson.new())
|
|
||||||
check p.isSome
|
|
||||||
|
|
|
||||||
|
|
@ -357,35 +357,3 @@ when not defined(testing) and isMainModule:
|
||||||
for val in items(x.row):
|
for val in items(x.row):
|
||||||
echo "##", val, "##"
|
echo "##", val, "##"
|
||||||
close(x)
|
close(x)
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
import os
|
|
||||||
import strutils
|
|
||||||
block: # Tests for reading the header row
|
|
||||||
let content = "\nOne,Two,Three,Four\n1,2,3,4\n10,20,30,40,\n100,200,300,400\n"
|
|
||||||
writeFile("temp.csv", content)
|
|
||||||
|
|
||||||
var p: CsvParser
|
|
||||||
p.open("temp.csv")
|
|
||||||
p.readHeaderRow()
|
|
||||||
while p.readRow():
|
|
||||||
let zeros = repeat('0', p.currRow-2)
|
|
||||||
doAssert p.rowEntry("One") == "1" & zeros
|
|
||||||
doAssert p.rowEntry("Two") == "2" & zeros
|
|
||||||
doAssert p.rowEntry("Three") == "3" & zeros
|
|
||||||
doAssert p.rowEntry("Four") == "4" & zeros
|
|
||||||
p.close()
|
|
||||||
|
|
||||||
when not defined(testing):
|
|
||||||
var parser: CsvParser
|
|
||||||
parser.open("temp.csv")
|
|
||||||
parser.readHeaderRow()
|
|
||||||
while parser.readRow():
|
|
||||||
echo "new row: "
|
|
||||||
for col in items(parser.headers):
|
|
||||||
echo "##", col, ":", parser.rowEntry(col), "##"
|
|
||||||
parser.close()
|
|
||||||
removeFile("temp.csv")
|
|
||||||
|
|
||||||
# Tidy up
|
|
||||||
removeFile("temp.csv")
|
|
||||||
|
|
|
||||||
|
|
@ -651,47 +651,4 @@ iterator interpolatedFragments*(s: string): tuple[kind: InterpolatedKind,
|
||||||
break
|
break
|
||||||
i = j
|
i = j
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
import sequtils
|
|
||||||
let input = "$test{} $this is ${an{ example}} "
|
|
||||||
let expected = @[(ikVar, "test"), (ikStr, "{} "), (ikVar, "this"),
|
|
||||||
(ikStr, " is "), (ikExpr, "an{ example}"), (ikStr, " ")]
|
|
||||||
doAssert toSeq(interpolatedFragments(input)) == expected
|
|
||||||
|
|
||||||
var value = 0
|
|
||||||
discard parseHex("0x38", value)
|
|
||||||
doAssert value == 56
|
|
||||||
|
|
||||||
value = -1
|
|
||||||
doAssert(parseSaturatedNatural("848", value) == 3)
|
|
||||||
doAssert value == 848
|
|
||||||
|
|
||||||
value = -1
|
|
||||||
discard parseSaturatedNatural("84899999999999999999324234243143142342135435342532453", value)
|
|
||||||
doAssert value == high(int)
|
|
||||||
|
|
||||||
value = -1
|
|
||||||
discard parseSaturatedNatural("9223372036854775808", value)
|
|
||||||
doAssert value == high(int)
|
|
||||||
|
|
||||||
value = -1
|
|
||||||
discard parseSaturatedNatural("9223372036854775807", value)
|
|
||||||
doAssert value == high(int)
|
|
||||||
|
|
||||||
value = -1
|
|
||||||
discard parseSaturatedNatural("18446744073709551616", value)
|
|
||||||
doAssert value == high(int)
|
|
||||||
|
|
||||||
value = -1
|
|
||||||
discard parseSaturatedNatural("18446744073709551615", value)
|
|
||||||
doAssert value == high(int)
|
|
||||||
|
|
||||||
value = -1
|
|
||||||
doAssert(parseSaturatedNatural("1_000_000", value) == 9)
|
|
||||||
doAssert value == 1_000_000
|
|
||||||
|
|
||||||
var i64Value: int64
|
|
||||||
discard parseBiggestInt("9223372036854775807", i64Value)
|
|
||||||
doAssert i64Value == 9223372036854775807
|
|
||||||
|
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
|
||||||
|
|
@ -206,9 +206,3 @@ runnableExamples:
|
||||||
doAssert decode("Mnchen-3ya-") == "Mnchen-3ya"
|
doAssert decode("Mnchen-3ya-") == "Mnchen-3ya"
|
||||||
doAssert decode("Mnchen-Ost-9db") == "München-Ost"
|
doAssert decode("Mnchen-Ost-9db") == "München-Ost"
|
||||||
doAssert decode("Bahnhof Mnchen-Ost-u6b") == "Bahnhof München-Ost"
|
doAssert decode("Bahnhof Mnchen-Ost-u6b") == "Bahnhof München-Ost"
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
assert(decode(encode("", "bücher")) == "bücher")
|
|
||||||
assert(decode(encode("münchen")) == "münchen")
|
|
||||||
assert encode("xn--", "münchen") == "xn--mnchen-3ya"
|
|
||||||
|
|
|
||||||
|
|
@ -651,57 +651,3 @@ when not defined(nimscript) and not defined(standalone):
|
||||||
randomize(convert(Seconds, Nanoseconds, now.toUnix) + now.nanosecond)
|
randomize(convert(Seconds, Nanoseconds, now.toUnix) + now.nanosecond)
|
||||||
|
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
import stats
|
|
||||||
|
|
||||||
proc main =
|
|
||||||
var occur: array[1000, int]
|
|
||||||
|
|
||||||
var x = 8234
|
|
||||||
for i in 0..100_000:
|
|
||||||
x = rand(high(occur))
|
|
||||||
inc occur[x]
|
|
||||||
for i, oc in occur:
|
|
||||||
if oc < 69:
|
|
||||||
doAssert false, "too few occurrences of " & $i
|
|
||||||
elif oc > 150:
|
|
||||||
doAssert false, "too many occurrences of " & $i
|
|
||||||
|
|
||||||
when false:
|
|
||||||
var rs: RunningStat
|
|
||||||
for j in 1..5:
|
|
||||||
for i in 1 .. 1_000:
|
|
||||||
rs.push(gauss())
|
|
||||||
echo("mean: ", rs.mean,
|
|
||||||
" stdDev: ", rs.standardDeviation(),
|
|
||||||
" min: ", rs.min,
|
|
||||||
" max: ", rs.max)
|
|
||||||
rs.clear()
|
|
||||||
|
|
||||||
var a = [0, 1]
|
|
||||||
shuffle(a)
|
|
||||||
doAssert a[0] == 1
|
|
||||||
doAssert a[1] == 0
|
|
||||||
|
|
||||||
doAssert rand(0) == 0
|
|
||||||
doAssert sample("a") == 'a'
|
|
||||||
|
|
||||||
when compileOption("rangeChecks"):
|
|
||||||
try:
|
|
||||||
discard rand(-1)
|
|
||||||
doAssert false
|
|
||||||
except RangeDefect:
|
|
||||||
discard
|
|
||||||
|
|
||||||
try:
|
|
||||||
discard rand(-1.0)
|
|
||||||
doAssert false
|
|
||||||
except RangeDefect:
|
|
||||||
discard
|
|
||||||
|
|
||||||
|
|
||||||
# don't use causes integer overflow
|
|
||||||
doAssert compiles(rand[int](low(int) .. high(int)))
|
|
||||||
|
|
||||||
main()
|
|
||||||
|
|
|
||||||
|
|
@ -279,100 +279,3 @@ proc hash*[T](x: Rational[T]): Hash =
|
||||||
h = h !& hash(copy.num)
|
h = h !& hash(copy.num)
|
||||||
h = h !& hash(copy.den)
|
h = h !& hash(copy.den)
|
||||||
result = !$h
|
result = !$h
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
var
|
|
||||||
z = Rational[int](num: 0, den: 1)
|
|
||||||
o = initRational(num = 1, den = 1)
|
|
||||||
a = initRational(1, 2)
|
|
||||||
b = -1 // -2
|
|
||||||
m1 = -1 // 1
|
|
||||||
tt = 10 // 2
|
|
||||||
|
|
||||||
assert(a == a)
|
|
||||||
assert( (a-a) == z)
|
|
||||||
assert( (a+b) == o)
|
|
||||||
assert( (a/b) == o)
|
|
||||||
assert( (a*b) == 1 // 4)
|
|
||||||
assert( (3/a) == 6 // 1)
|
|
||||||
assert( (a/3) == 1 // 6)
|
|
||||||
assert(a*b == 1 // 4)
|
|
||||||
assert(tt*z == z)
|
|
||||||
assert(10*a == tt)
|
|
||||||
assert(a*10 == tt)
|
|
||||||
assert(tt/10 == a)
|
|
||||||
assert(a-m1 == 3 // 2)
|
|
||||||
assert(a+m1 == -1 // 2)
|
|
||||||
assert(m1+tt == 16 // 4)
|
|
||||||
assert(m1-tt == 6 // -1)
|
|
||||||
|
|
||||||
assert(z < o)
|
|
||||||
assert(z <= o)
|
|
||||||
assert(z == z)
|
|
||||||
assert(cmp(z, o) < 0)
|
|
||||||
assert(cmp(o, z) > 0)
|
|
||||||
|
|
||||||
assert(o == o)
|
|
||||||
assert(o >= o)
|
|
||||||
assert(not(o > o))
|
|
||||||
assert(cmp(o, o) == 0)
|
|
||||||
assert(cmp(z, z) == 0)
|
|
||||||
assert(hash(o) == hash(o))
|
|
||||||
|
|
||||||
assert(a == b)
|
|
||||||
assert(a >= b)
|
|
||||||
assert(not(b > a))
|
|
||||||
assert(cmp(a, b) == 0)
|
|
||||||
assert(hash(a) == hash(b))
|
|
||||||
|
|
||||||
var x = 1//3
|
|
||||||
|
|
||||||
x *= 5//1
|
|
||||||
assert(x == 5//3)
|
|
||||||
x += 2 // 9
|
|
||||||
assert(x == 17//9)
|
|
||||||
x -= 9//18
|
|
||||||
assert(x == 25//18)
|
|
||||||
x /= 1//2
|
|
||||||
assert(x == 50//18)
|
|
||||||
|
|
||||||
var y = 1//3
|
|
||||||
|
|
||||||
y *= 4
|
|
||||||
assert(y == 4//3)
|
|
||||||
y += 5
|
|
||||||
assert(y == 19//3)
|
|
||||||
y -= 2
|
|
||||||
assert(y == 13//3)
|
|
||||||
y /= 9
|
|
||||||
assert(y == 13//27)
|
|
||||||
|
|
||||||
assert toRational(5) == 5//1
|
|
||||||
assert abs(toFloat(y) - 0.4814814814814815) < 1.0e-7
|
|
||||||
assert toInt(z) == 0
|
|
||||||
|
|
||||||
when sizeof(int) == 8:
|
|
||||||
assert toRational(0.98765432) == 2111111029 // 2137499919
|
|
||||||
assert toRational(PI) == 817696623 // 260280919
|
|
||||||
when sizeof(int) == 4:
|
|
||||||
assert toRational(0.98765432) == 80 // 81
|
|
||||||
assert toRational(PI) == 355 // 113
|
|
||||||
|
|
||||||
assert toRational(0.1) == 1 // 10
|
|
||||||
assert toRational(0.9) == 9 // 10
|
|
||||||
|
|
||||||
assert toRational(0.0) == 0 // 1
|
|
||||||
assert toRational(-0.25) == 1 // -4
|
|
||||||
assert toRational(3.2) == 16 // 5
|
|
||||||
assert toRational(0.33) == 33 // 100
|
|
||||||
assert toRational(0.22) == 11 // 50
|
|
||||||
assert toRational(10.0) == 10 // 1
|
|
||||||
|
|
||||||
assert (1//1) div (3//10) == 3
|
|
||||||
assert (-1//1) div (3//10) == -3
|
|
||||||
assert (3//10) mod (1//1) == 3//10
|
|
||||||
assert (-3//10) mod (1//1) == -3//10
|
|
||||||
assert floorDiv(1//1, 3//10) == 3
|
|
||||||
assert floorDiv(-1//1, 3//10) == -4
|
|
||||||
assert floorMod(3//10, 1//1) == 3//10
|
|
||||||
assert floorMod(-3//10, 1//1) == 7//10
|
|
||||||
|
|
|
||||||
|
|
@ -335,50 +335,3 @@ runnableExamples:
|
||||||
doAssert statistics.skewnessS() === 1.018350154434631
|
doAssert statistics.skewnessS() === 1.018350154434631
|
||||||
doAssert statistics.kurtosis() === -1.0
|
doAssert statistics.kurtosis() === -1.0
|
||||||
doAssert statistics.kurtosisS() === -0.7000000000000008
|
doAssert statistics.kurtosisS() === -0.7000000000000008
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
proc clean(x: float): float =
|
|
||||||
result = round(1.0e8*x).float * 1.0e-8
|
|
||||||
|
|
||||||
var rs: RunningStat
|
|
||||||
rs.push(@[1.0, 2.0, 1.0, 4.0, 1.0, 4.0, 1.0, 2.0])
|
|
||||||
doAssert(rs.n == 8)
|
|
||||||
doAssert(clean(rs.mean) == 2.0)
|
|
||||||
doAssert(clean(rs.variance()) == 1.5)
|
|
||||||
doAssert(clean(rs.varianceS()) == 1.71428571)
|
|
||||||
doAssert(clean(rs.skewness()) == 0.81649658)
|
|
||||||
doAssert(clean(rs.skewnessS()) == 1.01835015)
|
|
||||||
doAssert(clean(rs.kurtosis()) == -1.0)
|
|
||||||
doAssert(clean(rs.kurtosisS()) == -0.7000000000000001)
|
|
||||||
|
|
||||||
var rs1, rs2: RunningStat
|
|
||||||
rs1.push(@[1.0, 2.0, 1.0, 4.0])
|
|
||||||
rs2.push(@[1.0, 4.0, 1.0, 2.0])
|
|
||||||
let rs3 = rs1 + rs2
|
|
||||||
doAssert(clean(rs3.mom2) == clean(rs.mom2))
|
|
||||||
doAssert(clean(rs3.mom3) == clean(rs.mom3))
|
|
||||||
doAssert(clean(rs3.mom4) == clean(rs.mom4))
|
|
||||||
rs1 += rs2
|
|
||||||
doAssert(clean(rs1.mom2) == clean(rs.mom2))
|
|
||||||
doAssert(clean(rs1.mom3) == clean(rs.mom3))
|
|
||||||
doAssert(clean(rs1.mom4) == clean(rs.mom4))
|
|
||||||
rs1.clear()
|
|
||||||
rs1.push(@[1.0, 2.2, 1.4, 4.9])
|
|
||||||
doAssert(rs1.sum == 9.5)
|
|
||||||
doAssert(rs1.mean() == 2.375)
|
|
||||||
|
|
||||||
when not defined(cpu32):
|
|
||||||
# XXX For some reason on 32bit CPUs these results differ
|
|
||||||
var rr: RunningRegress
|
|
||||||
rr.push(@[0.0, 1.0, 2.8, 3.0, 4.0], @[0.0, 1.0, 2.3, 3.0, 4.0])
|
|
||||||
doAssert(rr.slope() == 0.9695585996955861)
|
|
||||||
doAssert(rr.intercept() == -0.03424657534246611)
|
|
||||||
doAssert(rr.correlation() == 0.9905100362239381)
|
|
||||||
var rr1, rr2: RunningRegress
|
|
||||||
rr1.push(@[0.0, 1.0], @[0.0, 1.0])
|
|
||||||
rr2.push(@[2.8, 3.0, 4.0], @[2.3, 3.0, 4.0])
|
|
||||||
let rr3 = rr1 + rr2
|
|
||||||
doAssert(rr3.correlation() == rr.correlation())
|
|
||||||
doAssert(clean(rr3.slope()) == clean(rr.slope()))
|
|
||||||
doAssert(clean(rr3.intercept()) == clean(rr.intercept()))
|
|
||||||
|
|
|
||||||
|
|
@ -1520,17 +1520,3 @@ when false:
|
||||||
var handle = open(filename, flags)
|
var handle = open(filename, flags)
|
||||||
if handle < 0: raise newEOS("posix.open() call failed")
|
if handle < 0: raise newEOS("posix.open() call failed")
|
||||||
result = newFileHandleStream(handle)
|
result = newFileHandleStream(handle)
|
||||||
|
|
||||||
when isMainModule and defined(testing):
|
|
||||||
var ss = newStringStream("The quick brown fox jumped over the lazy dog.\nThe lazy dog ran")
|
|
||||||
assert(ss.getPosition == 0)
|
|
||||||
assert(ss.peekStr(5) == "The q")
|
|
||||||
assert(ss.getPosition == 0) # haven't moved
|
|
||||||
assert(ss.readStr(5) == "The q")
|
|
||||||
assert(ss.getPosition == 5) # did move
|
|
||||||
assert(ss.peekLine() == "uick brown fox jumped over the lazy dog.")
|
|
||||||
assert(ss.getPosition == 5) # haven't moved
|
|
||||||
var str = newString(100)
|
|
||||||
assert(ss.peekLine(str))
|
|
||||||
assert(str == "uick brown fox jumped over the lazy dog.")
|
|
||||||
assert(ss.getPosition == 5) # haven't moved
|
|
||||||
|
|
|
||||||
|
|
@ -660,145 +660,3 @@ macro fmt*(pattern: string; openChar, closeChar: char): untyped =
|
||||||
doAssert """(()"foo" & "bar"())""".fmt(')', '(') == "(foobar)"
|
doAssert """(()"foo" & "bar"())""".fmt(')', '(') == "(foobar)"
|
||||||
doAssert """ ""{"123+123"}"" """.fmt('"', '"') == " \"{246}\" "
|
doAssert """ ""{"123+123"}"" """.fmt('"', '"') == " \"{246}\" "
|
||||||
strformatImpl(pattern, openChar.intVal.char, closeChar.intVal.char)
|
strformatImpl(pattern, openChar.intVal.char, closeChar.intVal.char)
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
template check(actual, expected: string) =
|
|
||||||
doAssert actual == expected
|
|
||||||
|
|
||||||
from strutils import toUpperAscii, repeat
|
|
||||||
|
|
||||||
# Basic tests
|
|
||||||
let s = "string"
|
|
||||||
check &"{0} {s}", "0 string"
|
|
||||||
check &"{s[0..2].toUpperAscii}", "STR"
|
|
||||||
check &"{-10:04}", "-010"
|
|
||||||
check &"{-10:<04}", "-010"
|
|
||||||
check &"{-10:>04}", "-010"
|
|
||||||
check &"0x{10:02X}", "0x0A"
|
|
||||||
|
|
||||||
check &"{10:#04X}", "0x0A"
|
|
||||||
|
|
||||||
check &"""{"test":#>5}""", "#test"
|
|
||||||
check &"""{"test":>5}""", " test"
|
|
||||||
|
|
||||||
check &"""{"test":#^7}""", "#test##"
|
|
||||||
|
|
||||||
check &"""{"test": <5}""", "test "
|
|
||||||
check &"""{"test":<5}""", "test "
|
|
||||||
check &"{1f:.3f}", "1.000"
|
|
||||||
check &"Hello, {s}!", "Hello, string!"
|
|
||||||
|
|
||||||
# Tests for identifiers without parenthesis
|
|
||||||
check &"{s} works{s}", "string worksstring"
|
|
||||||
check &"{s:>7}", " string"
|
|
||||||
doAssert(not compiles(&"{s_works}")) # parsed as identifier `s_works`
|
|
||||||
|
|
||||||
# Misc general tests
|
|
||||||
check &"{{}}", "{}"
|
|
||||||
check &"{0}%", "0%"
|
|
||||||
check &"{0}%asdf", "0%asdf"
|
|
||||||
check &("\n{\"\\n\"}\n"), "\n\n\n"
|
|
||||||
check &"""{"abc"}s""", "abcs"
|
|
||||||
|
|
||||||
# String tests
|
|
||||||
check &"""{"abc"}""", "abc"
|
|
||||||
check &"""{"abc":>4}""", " abc"
|
|
||||||
check &"""{"abc":<4}""", "abc "
|
|
||||||
check &"""{"":>4}""", " "
|
|
||||||
check &"""{"":<4}""", " "
|
|
||||||
|
|
||||||
# Int tests
|
|
||||||
check &"{12345}", "12345"
|
|
||||||
check &"{ - 12345}", "-12345"
|
|
||||||
check &"{12345:6}", " 12345"
|
|
||||||
check &"{12345:>6}", " 12345"
|
|
||||||
check &"{12345:4}", "12345"
|
|
||||||
check &"{12345:08}", "00012345"
|
|
||||||
check &"{-12345:08}", "-0012345"
|
|
||||||
check &"{0:0}", "0"
|
|
||||||
check &"{0:02}", "00"
|
|
||||||
check &"{-1:3}", " -1"
|
|
||||||
check &"{-1:03}", "-01"
|
|
||||||
check &"{10}", "10"
|
|
||||||
check &"{16:#X}", "0x10"
|
|
||||||
check &"{16:^#7X}", " 0x10 "
|
|
||||||
check &"{16:^+#7X}", " +0x10 "
|
|
||||||
|
|
||||||
# Hex tests
|
|
||||||
check &"{0:x}", "0"
|
|
||||||
check &"{-0:x}", "0"
|
|
||||||
check &"{255:x}", "ff"
|
|
||||||
check &"{255:X}", "FF"
|
|
||||||
check &"{-255:x}", "-ff"
|
|
||||||
check &"{-255:X}", "-FF"
|
|
||||||
check &"{255:x} uNaffeCteD CaSe", "ff uNaffeCteD CaSe"
|
|
||||||
check &"{255:X} uNaffeCteD CaSe", "FF uNaffeCteD CaSe"
|
|
||||||
check &"{255:4x}", " ff"
|
|
||||||
check &"{255:04x}", "00ff"
|
|
||||||
check &"{-255:4x}", " -ff"
|
|
||||||
check &"{-255:04x}", "-0ff"
|
|
||||||
|
|
||||||
# Float tests
|
|
||||||
check &"{123.456}", "123.456"
|
|
||||||
check &"{-123.456}", "-123.456"
|
|
||||||
check &"{123.456:.3f}", "123.456"
|
|
||||||
check &"{123.456:+.3f}", "+123.456"
|
|
||||||
check &"{-123.456:+.3f}", "-123.456"
|
|
||||||
check &"{-123.456:.3f}", "-123.456"
|
|
||||||
check &"{123.456:1g}", "123.456"
|
|
||||||
check &"{123.456:.1f}", "123.5"
|
|
||||||
check &"{123.456:.0f}", "123."
|
|
||||||
check &"{123.456:>9.3f}", " 123.456"
|
|
||||||
check &"{123.456:9.3f}", " 123.456"
|
|
||||||
check &"{123.456:>9.4f}", " 123.4560"
|
|
||||||
check &"{123.456:>9.0f}", " 123."
|
|
||||||
check &"{123.456:<9.4f}", "123.4560 "
|
|
||||||
|
|
||||||
# Float (scientific) tests
|
|
||||||
check &"{123.456:e}", "1.234560e+02"
|
|
||||||
check &"{123.456:>13e}", " 1.234560e+02"
|
|
||||||
check &"{123.456:<13e}", "1.234560e+02 "
|
|
||||||
check &"{123.456:.1e}", "1.2e+02"
|
|
||||||
check &"{123.456:.2e}", "1.23e+02"
|
|
||||||
check &"{123.456:.3e}", "1.235e+02"
|
|
||||||
|
|
||||||
# Note: times.format adheres to the format protocol. Test that this
|
|
||||||
# works:
|
|
||||||
import times
|
|
||||||
|
|
||||||
var dt = initDateTime(01, mJan, 2000, 00, 00, 00)
|
|
||||||
check &"{dt:yyyy-MM-dd}", "2000-01-01"
|
|
||||||
|
|
||||||
var tm = fromUnix(0)
|
|
||||||
discard &"{tm}"
|
|
||||||
|
|
||||||
var noww = now()
|
|
||||||
check &"{noww}", $noww
|
|
||||||
|
|
||||||
# Unicode string tests
|
|
||||||
check &"""{"αβγ"}""", "αβγ"
|
|
||||||
check &"""{"αβγ":>5}""", " αβγ"
|
|
||||||
check &"""{"αβγ":<5}""", "αβγ "
|
|
||||||
check &"""a{"a"}α{"α"}€{"€"}𐍈{"𐍈"}""", "aaαα€€𐍈𐍈"
|
|
||||||
check &"""a{"a":2}α{"α":2}€{"€":2}𐍈{"𐍈":2}""", "aa αα €€ 𐍈𐍈 "
|
|
||||||
# Invalid unicode sequences should be handled as plain strings.
|
|
||||||
# Invalid examples taken from: https://stackoverflow.com/a/3886015/1804173
|
|
||||||
let invalidUtf8 = [
|
|
||||||
"\xc3\x28", "\xa0\xa1",
|
|
||||||
"\xe2\x28\xa1", "\xe2\x82\x28",
|
|
||||||
"\xf0\x28\x8c\xbc", "\xf0\x90\x28\xbc", "\xf0\x28\x8c\x28"
|
|
||||||
]
|
|
||||||
for s in invalidUtf8:
|
|
||||||
check &"{s:>5}", repeat(" ", 5-s.len) & s
|
|
||||||
|
|
||||||
# bug #11089
|
|
||||||
let flfoo: float = 1.0
|
|
||||||
check &"{flfoo}", "1.0"
|
|
||||||
|
|
||||||
# bug #11092
|
|
||||||
check &"{high(int64)}", "9223372036854775807"
|
|
||||||
check &"{low(int64)}", "-9223372036854775808"
|
|
||||||
|
|
||||||
doAssert fmt"{'a'} {'b'}" == "a b"
|
|
||||||
|
|
||||||
echo("All tests ok")
|
|
||||||
|
|
|
||||||
|
|
@ -84,24 +84,3 @@ proc rpartition*(s: string, sep: string): (string, string, string)
|
||||||
doAssert rpartition("foofoobar", "bar") == ("foofoo", "bar", "")
|
doAssert rpartition("foofoobar", "bar") == ("foofoo", "bar", "")
|
||||||
|
|
||||||
return partition(s, sep, right = true)
|
return partition(s, sep, right = true)
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
doAssert expandTabs("\t", 4) == " "
|
|
||||||
doAssert expandTabs("\tfoo\t", 4) == " foo "
|
|
||||||
doAssert expandTabs("\tfoo\tbar", 4) == " foo bar"
|
|
||||||
doAssert expandTabs("\tfoo\tbar\t", 4) == " foo bar "
|
|
||||||
doAssert expandTabs("", 4) == ""
|
|
||||||
doAssert expandTabs("", 0) == ""
|
|
||||||
doAssert expandTabs("\t\t\t", 0) == ""
|
|
||||||
|
|
||||||
doAssert partition("foo:bar", ":") == ("foo", ":", "bar")
|
|
||||||
doAssert partition("foobarbar", "bar") == ("foo", "bar", "bar")
|
|
||||||
doAssert partition("foobarbar", "bank") == ("foobarbar", "", "")
|
|
||||||
doAssert partition("foobarbar", "foo") == ("", "foo", "barbar")
|
|
||||||
doAssert partition("foofoobar", "bar") == ("foofoo", "bar", "")
|
|
||||||
|
|
||||||
doAssert rpartition("foo:bar", ":") == ("foo", ":", "bar")
|
|
||||||
doAssert rpartition("foobarbar", "bar") == ("foobar", "bar", "")
|
|
||||||
doAssert rpartition("foobarbar", "bank") == ("", "", "foobarbar")
|
|
||||||
doAssert rpartition("foobarbar", "foo") == ("", "foo", "barbar")
|
|
||||||
doAssert rpartition("foofoobar", "bar") == ("foofoo", "bar", "")
|
|
||||||
|
|
|
||||||
|
|
@ -633,115 +633,3 @@ macro scanp*(input, idx: typed; pattern: varargs[untyped]): bool =
|
||||||
result.add res
|
result.add res
|
||||||
when defined(debugScanp):
|
when defined(debugScanp):
|
||||||
echo repr result
|
echo repr result
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
proc twoDigits(input: string; x: var int; start: int): int =
|
|
||||||
if start+1 < input.len and input[start] == '0' and input[start+1] == '0':
|
|
||||||
result = 2
|
|
||||||
x = 13
|
|
||||||
else:
|
|
||||||
result = 0
|
|
||||||
|
|
||||||
proc someSep(input: string; start: int; seps: set[char] = {';', ',', '-', '.'}): int =
|
|
||||||
result = 0
|
|
||||||
while start+result < input.len and input[start+result] in seps: inc result
|
|
||||||
|
|
||||||
proc demangle(s: string; res: var string; start: int): int =
|
|
||||||
while result+start < s.len and s[result+start] in {'_', '@'}: inc result
|
|
||||||
res = ""
|
|
||||||
while result+start < s.len and s[result+start] > ' ' and s[result+start] != '_':
|
|
||||||
res.add s[result+start]
|
|
||||||
inc result
|
|
||||||
while result+start < s.len and s[result+start] > ' ':
|
|
||||||
inc result
|
|
||||||
|
|
||||||
proc parseGDB(resp: string): seq[string] =
|
|
||||||
const
|
|
||||||
digits = {'0'..'9'}
|
|
||||||
hexdigits = digits + {'a'..'f', 'A'..'F'}
|
|
||||||
whites = {' ', '\t', '\C', '\L'}
|
|
||||||
result = @[]
|
|
||||||
var idx = 0
|
|
||||||
while true:
|
|
||||||
var prc = ""
|
|
||||||
var info = ""
|
|
||||||
if scanp(resp, idx, *`whites`, '#', *`digits`, +`whites`, ?("0x", *`hexdigits`, " in "),
|
|
||||||
demangle($input, prc, $index), *`whites`, '(', * ~ ')', ')',
|
|
||||||
*`whites`, "at ", +(~{'\C', '\L'} -> info.add($_))):
|
|
||||||
result.add prc & " " & info
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
|
|
||||||
var key, val: string
|
|
||||||
var intval: int
|
|
||||||
var floatval: float
|
|
||||||
doAssert scanf("abc:: xyz 89 33.25", "$w$s::$s$w$s$i $f", key, val, intval, floatVal)
|
|
||||||
doAssert key == "abc"
|
|
||||||
doAssert val == "xyz"
|
|
||||||
doAssert intval == 89
|
|
||||||
doAssert floatVal == 33.25
|
|
||||||
|
|
||||||
var binval: int
|
|
||||||
var octval: int
|
|
||||||
var hexval: int
|
|
||||||
doAssert scanf("0b0101 0o1234 0xabcd", "$b$s$o$s$h", binval, octval, hexval)
|
|
||||||
doAssert binval == 0b0101
|
|
||||||
doAssert octval == 0o1234
|
|
||||||
doAssert hexval == 0xabcd
|
|
||||||
|
|
||||||
let xx = scanf("$abc", "$$$i", intval)
|
|
||||||
doAssert xx == false
|
|
||||||
|
|
||||||
|
|
||||||
let xx2 = scanf("$1234", "$$$i", intval)
|
|
||||||
doAssert xx2
|
|
||||||
|
|
||||||
let yy = scanf(";.--Breakpoint00 [output]",
|
|
||||||
"$[someSep]Breakpoint${twoDigits}$[someSep({';','.','-'})] [$+]$.",
|
|
||||||
intVal, key)
|
|
||||||
doAssert yy
|
|
||||||
doAssert key == "output"
|
|
||||||
doAssert intVal == 13
|
|
||||||
|
|
||||||
var ident = ""
|
|
||||||
var idx = 0
|
|
||||||
let zz = scanp("foobar x x x xWZ", idx, +{'a'..'z'} -> add(ident, $_), *(*{
|
|
||||||
' ', '\t'}, "x"), ~'U', "Z")
|
|
||||||
doAssert zz
|
|
||||||
doAssert ident == "foobar"
|
|
||||||
|
|
||||||
const digits = {'0'..'9'}
|
|
||||||
var year = 0
|
|
||||||
var idx2 = 0
|
|
||||||
if scanp("201655-8-9", idx2, `digits`{4, 6} -> (year = year * 10 + ord($_) -
|
|
||||||
ord('0')), "-8", "-9"):
|
|
||||||
doAssert year == 201655
|
|
||||||
|
|
||||||
const gdbOut = """
|
|
||||||
#0 @foo_96013_1208911747@8 (x0=...)
|
|
||||||
at c:/users/anwender/projects/nim/temp.nim:11
|
|
||||||
#1 0x00417754 in tempInit000 () at c:/users/anwender/projects/nim/temp.nim:13
|
|
||||||
#2 0x0041768d in NimMainInner ()
|
|
||||||
at c:/users/anwender/projects/nim/lib/system.nim:2605
|
|
||||||
#3 0x004176b1 in NimMain ()
|
|
||||||
at c:/users/anwender/projects/nim/lib/system.nim:2613
|
|
||||||
#4 0x004176db in main (argc=1, args=0x712cc8, env=0x711ca8)
|
|
||||||
at c:/users/anwender/projects/nim/lib/system.nim:2620"""
|
|
||||||
const result = @["foo c:/users/anwender/projects/nim/temp.nim:11",
|
|
||||||
"tempInit000 c:/users/anwender/projects/nim/temp.nim:13",
|
|
||||||
"NimMainInner c:/users/anwender/projects/nim/lib/system.nim:2605",
|
|
||||||
"NimMain c:/users/anwender/projects/nim/lib/system.nim:2613",
|
|
||||||
"main c:/users/anwender/projects/nim/lib/system.nim:2620"]
|
|
||||||
#doAssert parseGDB(gdbOut) == result
|
|
||||||
|
|
||||||
# bug #6487
|
|
||||||
var count = 0
|
|
||||||
|
|
||||||
proc test(): string =
|
|
||||||
inc count
|
|
||||||
result = ",123123"
|
|
||||||
|
|
||||||
var a: int
|
|
||||||
discard scanf(test(), ",$i", a)
|
|
||||||
doAssert count == 1
|
|
||||||
|
|
|
||||||
|
|
@ -420,15 +420,3 @@ proc `%`*(f: string, t: StringTableRef, flags: set[FormatFlag] = {}): string {.
|
||||||
else:
|
else:
|
||||||
add(result, f[i])
|
add(result, f[i])
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
var x = {"k": "v", "11": "22", "565": "67"}.newStringTable
|
|
||||||
assert x["k"] == "v"
|
|
||||||
assert x["11"] == "22"
|
|
||||||
assert x["565"] == "67"
|
|
||||||
x["11"] = "23"
|
|
||||||
assert x["11"] == "23"
|
|
||||||
|
|
||||||
x.clear(modeCaseInsensitive)
|
|
||||||
x["11"] = "22"
|
|
||||||
assert x["11"] == "22"
|
|
||||||
|
|
|
||||||
|
|
@ -2920,220 +2920,3 @@ proc isEmptyOrWhitespace*(s: string): bool {.noSideEffect, rtl,
|
||||||
extern: "nsuIsEmptyOrWhitespace".} =
|
extern: "nsuIsEmptyOrWhitespace".} =
|
||||||
## Checks if `s` is empty or consists entirely of whitespace characters.
|
## Checks if `s` is empty or consists entirely of whitespace characters.
|
||||||
result = s.allCharsInSet(Whitespace)
|
result = s.allCharsInSet(Whitespace)
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
proc nonStaticTests =
|
|
||||||
doAssert formatBiggestFloat(1234.567, ffDecimal, -1) == "1234.567000"
|
|
||||||
when not defined(js):
|
|
||||||
doAssert formatBiggestFloat(1234.567, ffDecimal, 0) == "1235." # bugs 8242, 12586
|
|
||||||
doAssert formatBiggestFloat(1234.567, ffDecimal, 1) == "1234.6"
|
|
||||||
doAssert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001"
|
|
||||||
doAssert formatBiggestFloat(0.00000000001, ffScientific, 1, ',') in
|
|
||||||
["1,0e-11", "1,0e-011"]
|
|
||||||
# bug #6589
|
|
||||||
when not defined(js):
|
|
||||||
doAssert formatFloat(123.456, ffScientific, precision = -1) == "1.234560e+02"
|
|
||||||
|
|
||||||
doAssert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c"
|
|
||||||
doAssert "${1}12 ${-1}$2" % ["a", "b"] == "a12 bb"
|
|
||||||
|
|
||||||
block: # formatSize tests
|
|
||||||
when not defined(js):
|
|
||||||
doAssert formatSize((1'i64 shl 31) + (300'i64 shl 20)) == "2.293GiB" # <=== bug #8231
|
|
||||||
doAssert formatSize((2.234*1024*1024).int) == "2.234MiB"
|
|
||||||
doAssert formatSize(4096) == "4KiB"
|
|
||||||
doAssert formatSize(4096, prefix = bpColloquial, includeSpace = true) == "4 kB"
|
|
||||||
doAssert formatSize(4096, includeSpace = true) == "4 KiB"
|
|
||||||
doAssert formatSize(5_378_934, prefix = bpColloquial, decimalSep = ',') == "5,13MB"
|
|
||||||
|
|
||||||
block: # formatEng tests
|
|
||||||
doAssert formatEng(0, 2, trim = false) == "0.00"
|
|
||||||
doAssert formatEng(0, 2) == "0"
|
|
||||||
doAssert formatEng(53, 2, trim = false) == "53.00"
|
|
||||||
doAssert formatEng(0.053, 2, trim = false) == "53.00e-3"
|
|
||||||
doAssert formatEng(0.053, 4, trim = false) == "53.0000e-3"
|
|
||||||
doAssert formatEng(0.053, 4, trim = true) == "53e-3"
|
|
||||||
doAssert formatEng(0.053, 0) == "53e-3"
|
|
||||||
doAssert formatEng(52731234) == "52.731234e6"
|
|
||||||
doAssert formatEng(-52731234) == "-52.731234e6"
|
|
||||||
doAssert formatEng(52731234, 1) == "52.7e6"
|
|
||||||
doAssert formatEng(-52731234, 1) == "-52.7e6"
|
|
||||||
doAssert formatEng(52731234, 1, decimalSep = ',') == "52,7e6"
|
|
||||||
doAssert formatEng(-52731234, 1, decimalSep = ',') == "-52,7e6"
|
|
||||||
|
|
||||||
doAssert formatEng(4100, siPrefix = true, unit = "V") == "4.1 kV"
|
|
||||||
doAssert formatEng(4.1, siPrefix = true, unit = "V",
|
|
||||||
useUnitSpace = true) == "4.1 V"
|
|
||||||
doAssert formatEng(4.1, siPrefix = true) == "4.1" # Note lack of space
|
|
||||||
doAssert formatEng(4100, siPrefix = true) == "4.1 k"
|
|
||||||
doAssert formatEng(4.1, siPrefix = true, unit = "",
|
|
||||||
useUnitSpace = true) == "4.1 " # Includes space
|
|
||||||
doAssert formatEng(4100, siPrefix = true, unit = "") == "4.1 k"
|
|
||||||
doAssert formatEng(4100) == "4.1e3"
|
|
||||||
doAssert formatEng(4100, unit = "V", useUnitSpace = true) == "4.1e3 V"
|
|
||||||
doAssert formatEng(4100, unit = "", useUnitSpace = true) == "4.1e3 "
|
|
||||||
# Don't use SI prefix as number is too big
|
|
||||||
doAssert formatEng(3.1e22, siPrefix = true, unit = "a",
|
|
||||||
useUnitSpace = true) == "31e21 a"
|
|
||||||
# Don't use SI prefix as number is too small
|
|
||||||
doAssert formatEng(3.1e-25, siPrefix = true, unit = "A",
|
|
||||||
useUnitSpace = true) == "310e-27 A"
|
|
||||||
|
|
||||||
proc staticTests =
|
|
||||||
doAssert align("abc", 4) == " abc"
|
|
||||||
doAssert align("a", 0) == "a"
|
|
||||||
doAssert align("1232", 6) == " 1232"
|
|
||||||
doAssert align("1232", 6, '#') == "##1232"
|
|
||||||
|
|
||||||
doAssert alignLeft("abc", 4) == "abc "
|
|
||||||
doAssert alignLeft("a", 0) == "a"
|
|
||||||
doAssert alignLeft("1232", 6) == "1232 "
|
|
||||||
doAssert alignLeft("1232", 6, '#') == "1232##"
|
|
||||||
|
|
||||||
doAssert "$animal eats $food." % ["animal", "The cat", "food", "fish"] ==
|
|
||||||
"The cat eats fish."
|
|
||||||
|
|
||||||
doAssert "-ld a-ldz -ld".replaceWord("-ld") == " a-ldz "
|
|
||||||
doAssert "-lda-ldz -ld abc".replaceWord("-ld") == "-lda-ldz abc"
|
|
||||||
|
|
||||||
doAssert "-lda-ldz -ld abc".replaceWord("") == "-lda-ldz -ld abc"
|
|
||||||
doAssert "oo".replace("", "abc") == "oo"
|
|
||||||
|
|
||||||
type MyEnum = enum enA, enB, enC, enuD, enE
|
|
||||||
doAssert parseEnum[MyEnum]("enu_D") == enuD
|
|
||||||
|
|
||||||
doAssert parseEnum("invalid enum value", enC) == enC
|
|
||||||
|
|
||||||
doAssert center("foo", 13) == " foo "
|
|
||||||
doAssert center("foo", 0) == "foo"
|
|
||||||
doAssert center("foo", 3, fillChar = 'a') == "foo"
|
|
||||||
doAssert center("foo", 10, fillChar = '\t') == "\t\t\tfoo\t\t\t\t"
|
|
||||||
|
|
||||||
doAssert count("foofoofoo", "foofoo") == 1
|
|
||||||
doAssert count("foofoofoo", "foofoo", overlapping = true) == 2
|
|
||||||
doAssert count("foofoofoo", 'f') == 3
|
|
||||||
doAssert count("foofoofoobar", {'f', 'b'}) == 4
|
|
||||||
|
|
||||||
doAssert strip(" foofoofoo ") == "foofoofoo"
|
|
||||||
doAssert strip("sfoofoofoos", chars = {'s'}) == "foofoofoo"
|
|
||||||
doAssert strip("barfoofoofoobar", chars = {'b', 'a', 'r'}) == "foofoofoo"
|
|
||||||
doAssert strip("stripme but don't strip this stripme",
|
|
||||||
chars = {'s', 't', 'r', 'i', 'p', 'm', 'e'}) ==
|
|
||||||
" but don't strip this "
|
|
||||||
doAssert strip("sfoofoofoos", leading = false, chars = {'s'}) == "sfoofoofoo"
|
|
||||||
doAssert strip("sfoofoofoos", trailing = false, chars = {'s'}) == "foofoofoos"
|
|
||||||
|
|
||||||
doAssert " foo\n bar".indent(4, "Q") == "QQQQ foo\nQQQQ bar"
|
|
||||||
|
|
||||||
doAssert "abba".multiReplace(("a", "b"), ("b", "a")) == "baab"
|
|
||||||
doAssert "Hello World.".multiReplace(("ello", "ELLO"), ("World.",
|
|
||||||
"PEOPLE!")) == "HELLO PEOPLE!"
|
|
||||||
doAssert "aaaa".multiReplace(("a", "aa"), ("aa", "bb")) == "aaaaaaaa"
|
|
||||||
|
|
||||||
doAssert isAlphaAscii('r')
|
|
||||||
doAssert isAlphaAscii('A')
|
|
||||||
doAssert(not isAlphaAscii('$'))
|
|
||||||
|
|
||||||
doAssert isAlphaNumeric('3')
|
|
||||||
doAssert isAlphaNumeric('R')
|
|
||||||
doAssert(not isAlphaNumeric('!'))
|
|
||||||
|
|
||||||
doAssert isDigit('3')
|
|
||||||
doAssert(not isDigit('a'))
|
|
||||||
doAssert(not isDigit('%'))
|
|
||||||
|
|
||||||
doAssert isSpaceAscii('\t')
|
|
||||||
doAssert isSpaceAscii('\l')
|
|
||||||
doAssert(not isSpaceAscii('A'))
|
|
||||||
|
|
||||||
doAssert(isEmptyOrWhitespace(""))
|
|
||||||
doAssert(isEmptyOrWhitespace(" "))
|
|
||||||
doAssert(isEmptyOrWhitespace("\t\l \v\r\f"))
|
|
||||||
doAssert(not isEmptyOrWhitespace("ABc \td"))
|
|
||||||
|
|
||||||
doAssert isLowerAscii('a')
|
|
||||||
doAssert isLowerAscii('z')
|
|
||||||
doAssert(not isLowerAscii('A'))
|
|
||||||
doAssert(not isLowerAscii('5'))
|
|
||||||
doAssert(not isLowerAscii('&'))
|
|
||||||
doAssert(not isLowerAscii(' '))
|
|
||||||
|
|
||||||
doAssert isUpperAscii('A')
|
|
||||||
doAssert(not isUpperAscii('b'))
|
|
||||||
doAssert(not isUpperAscii('5'))
|
|
||||||
doAssert(not isUpperAscii('%'))
|
|
||||||
|
|
||||||
doAssert rsplit("foo bar", seps = Whitespace) == @["foo", "bar"]
|
|
||||||
doAssert rsplit(" foo bar", seps = Whitespace, maxsplit = 1) == @[" foo", "bar"]
|
|
||||||
doAssert rsplit(" foo bar ", seps = Whitespace, maxsplit = 1) == @[
|
|
||||||
" foo bar", ""]
|
|
||||||
doAssert rsplit(":foo:bar", sep = ':') == @["", "foo", "bar"]
|
|
||||||
doAssert rsplit(":foo:bar", sep = ':', maxsplit = 2) == @["", "foo", "bar"]
|
|
||||||
doAssert rsplit(":foo:bar", sep = ':', maxsplit = 3) == @["", "foo", "bar"]
|
|
||||||
doAssert rsplit("foothebar", sep = "the") == @["foo", "bar"]
|
|
||||||
|
|
||||||
doAssert(unescape(r"\x013", "", "") == "\x013")
|
|
||||||
|
|
||||||
doAssert join(["foo", "bar", "baz"]) == "foobarbaz"
|
|
||||||
doAssert join(@["foo", "bar", "baz"], ", ") == "foo, bar, baz"
|
|
||||||
doAssert join([1, 2, 3]) == "123"
|
|
||||||
doAssert join(@[1, 2, 3], ", ") == "1, 2, 3"
|
|
||||||
|
|
||||||
doAssert """~~!!foo
|
|
||||||
~~!!bar
|
|
||||||
~~!!baz""".unindent(2, "~~!!") == "foo\nbar\nbaz"
|
|
||||||
|
|
||||||
doAssert """~~!!foo
|
|
||||||
~~!!bar
|
|
||||||
~~!!baz""".unindent(2, "~~!!aa") == "~~!!foo\n~~!!bar\n~~!!baz"
|
|
||||||
doAssert """~~foo
|
|
||||||
~~ bar
|
|
||||||
~~ baz""".unindent(4, "~") == "foo\n bar\n baz"
|
|
||||||
doAssert """foo
|
|
||||||
bar
|
|
||||||
baz
|
|
||||||
""".unindent(4) == "foo\nbar\nbaz\n"
|
|
||||||
doAssert """foo
|
|
||||||
bar
|
|
||||||
baz
|
|
||||||
""".unindent(2) == "foo\n bar\n baz\n"
|
|
||||||
doAssert """foo
|
|
||||||
bar
|
|
||||||
baz
|
|
||||||
""".unindent(100) == "foo\nbar\nbaz\n"
|
|
||||||
|
|
||||||
doAssert """foo
|
|
||||||
foo
|
|
||||||
bar
|
|
||||||
""".unindent() == "foo\nfoo\nbar\n"
|
|
||||||
|
|
||||||
let s = " this is an example "
|
|
||||||
let s2 = ":this;is;an:example;;"
|
|
||||||
|
|
||||||
doAssert s.split() == @["", "this", "is", "an", "example", "", ""]
|
|
||||||
doAssert s2.split(seps = {':', ';'}) == @["", "this", "is", "an", "example",
|
|
||||||
"", ""]
|
|
||||||
doAssert s.split(maxsplit = 4) == @["", "this", "is", "an", "example "]
|
|
||||||
doAssert s.split(' ', maxsplit = 1) == @["", "this is an example "]
|
|
||||||
doAssert s.split(" ", maxsplit = 4) == @["", "this", "is", "an", "example "]
|
|
||||||
|
|
||||||
doAssert s.splitWhitespace() == @["this", "is", "an", "example"]
|
|
||||||
doAssert s.splitWhitespace(maxsplit = 1) == @["this", "is an example "]
|
|
||||||
doAssert s.splitWhitespace(maxsplit = 2) == @["this", "is", "an example "]
|
|
||||||
doAssert s.splitWhitespace(maxsplit = 3) == @["this", "is", "an", "example "]
|
|
||||||
doAssert s.splitWhitespace(maxsplit = 4) == @["this", "is", "an", "example"]
|
|
||||||
|
|
||||||
block: # startsWith / endsWith char tests
|
|
||||||
var s = "abcdef"
|
|
||||||
doAssert s.startsWith('a')
|
|
||||||
doAssert s.startsWith('b') == false
|
|
||||||
doAssert s.endsWith('f')
|
|
||||||
doAssert s.endsWith('a') == false
|
|
||||||
doAssert s.endsWith('\0') == false
|
|
||||||
|
|
||||||
#echo("strutils tests passed")
|
|
||||||
|
|
||||||
nonStaticTests()
|
|
||||||
staticTests()
|
|
||||||
static: staticTests()
|
|
||||||
|
|
|
||||||
|
|
@ -1169,219 +1169,3 @@ proc alignLeft*(s: string, count: Natural, padding = ' '.Rune): string {.
|
||||||
result.add padStr
|
result.add padStr
|
||||||
else:
|
else:
|
||||||
result = s
|
result = s
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
|
|
||||||
proc asRune(s: static[string]): Rune =
|
|
||||||
## Compile-time conversion proc for converting string literals to a Rune
|
|
||||||
## value. Returns the first Rune of the specified string.
|
|
||||||
##
|
|
||||||
## Shortcuts code like ``"å".runeAt(0)`` to ``"å".asRune`` and returns a
|
|
||||||
## compile-time constant.
|
|
||||||
if s.len == 0: Rune(0)
|
|
||||||
else: s.runeAt(0)
|
|
||||||
|
|
||||||
let
|
|
||||||
someString = "öÑ"
|
|
||||||
someRunes = toRunes(someString)
|
|
||||||
compared = (someString == $someRunes)
|
|
||||||
doAssert compared == true
|
|
||||||
|
|
||||||
proc testReplacements(word: string): string =
|
|
||||||
case word
|
|
||||||
of "two":
|
|
||||||
return "2"
|
|
||||||
of "foo":
|
|
||||||
return "BAR"
|
|
||||||
of "βeta":
|
|
||||||
return "beta"
|
|
||||||
of "alpha":
|
|
||||||
return "αlpha"
|
|
||||||
else:
|
|
||||||
return "12345"
|
|
||||||
|
|
||||||
doAssert translate("two not alpha foo βeta", testReplacements) == "2 12345 αlpha BAR beta"
|
|
||||||
doAssert translate(" two not foo βeta ", testReplacements) == " 2 12345 BAR beta "
|
|
||||||
|
|
||||||
doAssert title("foo bar") == "Foo Bar"
|
|
||||||
doAssert title("αlpha βeta γamma") == "Αlpha Βeta Γamma"
|
|
||||||
doAssert title("") == ""
|
|
||||||
|
|
||||||
doAssert capitalize("βeta") == "Βeta"
|
|
||||||
doAssert capitalize("foo") == "Foo"
|
|
||||||
doAssert capitalize("") == ""
|
|
||||||
|
|
||||||
doAssert swapCase("FooBar") == "fOObAR"
|
|
||||||
doAssert swapCase(" ") == " "
|
|
||||||
doAssert swapCase("Αlpha Βeta Γamma") == "αLPHA βETA γAMMA"
|
|
||||||
doAssert swapCase("a✓B") == "A✓b"
|
|
||||||
doAssert swapCase("Јамогујестистаклоитоминештети") == "јАМОГУЈЕСТИСТАКЛОИТОМИНЕШТЕТИ"
|
|
||||||
doAssert swapCase("ὕαλονϕαγεῖνδύναμαιτοῦτοοὔμεβλάπτει") == "ὝΑΛΟΝΦΑΓΕῖΝΔΎΝΑΜΑΙΤΟῦΤΟΟὔΜΕΒΛΆΠΤΕΙ"
|
|
||||||
doAssert swapCase("Կրնամապակիուտեևինծիանհանգիստչըներ") == "կՐՆԱՄԱՊԱԿԻՈՒՏԵևԻՆԾԻԱՆՀԱՆԳԻՍՏՉԸՆԵՐ"
|
|
||||||
doAssert swapCase("") == ""
|
|
||||||
|
|
||||||
doAssert isAlpha("r")
|
|
||||||
doAssert isAlpha("α")
|
|
||||||
doAssert isAlpha("ϙ")
|
|
||||||
doAssert isAlpha("ஶ")
|
|
||||||
doAssert(not isAlpha("$"))
|
|
||||||
doAssert(not isAlpha(""))
|
|
||||||
|
|
||||||
doAssert isAlpha("Βeta")
|
|
||||||
doAssert isAlpha("Args")
|
|
||||||
doAssert isAlpha("𐌼𐌰𐌲𐌲𐌻𐌴𐍃𐍄𐌰𐌽")
|
|
||||||
doAssert isAlpha("ὕαλονϕαγεῖνδύναμαιτοῦτοοὔμεβλάπτει")
|
|
||||||
doAssert isAlpha("Јамогујестистаклоитоминештети")
|
|
||||||
doAssert isAlpha("Կրնամապակիուտեևինծիանհանգիստչըներ")
|
|
||||||
doAssert(not isAlpha("$Foo✓"))
|
|
||||||
doAssert(not isAlpha("⠙⠕⠑⠎⠝⠞"))
|
|
||||||
|
|
||||||
doAssert isSpace("\t")
|
|
||||||
doAssert isSpace("\l")
|
|
||||||
doAssert(not isSpace("Β"))
|
|
||||||
doAssert(not isSpace("Βeta"))
|
|
||||||
|
|
||||||
doAssert isSpace("\t\l \v\r\f")
|
|
||||||
doAssert isSpace(" ")
|
|
||||||
doAssert(not isSpace(""))
|
|
||||||
doAssert(not isSpace("ΑΓc \td"))
|
|
||||||
|
|
||||||
doAssert(not isLower(' '.Rune))
|
|
||||||
|
|
||||||
doAssert(not isUpper(' '.Rune))
|
|
||||||
|
|
||||||
doAssert toUpper("Γ") == "Γ"
|
|
||||||
doAssert toUpper("b") == "B"
|
|
||||||
doAssert toUpper("α") == "Α"
|
|
||||||
doAssert toUpper("✓") == "✓"
|
|
||||||
doAssert toUpper("ϙ") == "Ϙ"
|
|
||||||
doAssert toUpper("") == ""
|
|
||||||
|
|
||||||
doAssert toUpper("ΑΒΓ") == "ΑΒΓ"
|
|
||||||
doAssert toUpper("AAccβ") == "AACCΒ"
|
|
||||||
doAssert toUpper("A✓$β") == "A✓$Β"
|
|
||||||
|
|
||||||
doAssert toLower("a") == "a"
|
|
||||||
doAssert toLower("γ") == "γ"
|
|
||||||
doAssert toLower("Γ") == "γ"
|
|
||||||
doAssert toLower("4") == "4"
|
|
||||||
doAssert toLower("Ϙ") == "ϙ"
|
|
||||||
doAssert toLower("") == ""
|
|
||||||
|
|
||||||
doAssert toLower("abcdγ") == "abcdγ"
|
|
||||||
doAssert toLower("abCDΓ") == "abcdγ"
|
|
||||||
doAssert toLower("33aaΓ") == "33aaγ"
|
|
||||||
|
|
||||||
doAssert reversed("Reverse this!") == "!siht esreveR"
|
|
||||||
doAssert reversed("先秦兩漢") == "漢兩秦先"
|
|
||||||
doAssert reversed("as⃝df̅") == "f̅ds⃝a"
|
|
||||||
doAssert reversed("a⃞b⃞c⃞") == "c⃞b⃞a⃞"
|
|
||||||
doAssert reversed("ὕαλονϕαγεῖνδύναμαιτοῦτοοὔμεβλάπτει") == "ιετπάλβεμὔοοτῦοτιαμανύδνῖεγαϕνολαὕ"
|
|
||||||
doAssert reversed("Јамогујестистаклоитоминештети") == "итетшенимотиолкатситсејугомаЈ"
|
|
||||||
doAssert reversed("Կրնամապակիուտեևինծիանհանգիստչըներ") == "րենըչտսիգնահնաիծնիևետւոիկապամանրԿ"
|
|
||||||
doAssert len(toRunes("as⃝df̅")) == runeLen("as⃝df̅")
|
|
||||||
const test = "as⃝"
|
|
||||||
doAssert lastRune(test, test.len-1)[1] == 3
|
|
||||||
doAssert graphemeLen("è", 0) == 2
|
|
||||||
|
|
||||||
# test for rune positioning and runeSubStr()
|
|
||||||
let s = "Hänsel ««: 10,00€"
|
|
||||||
|
|
||||||
var t = ""
|
|
||||||
for c in s.utf8:
|
|
||||||
t.add c
|
|
||||||
|
|
||||||
doAssert(s == t)
|
|
||||||
|
|
||||||
doAssert(runeReverseOffset(s, 1) == (20, 18))
|
|
||||||
doAssert(runeReverseOffset(s, 19) == (-1, 18))
|
|
||||||
|
|
||||||
doAssert(runeStrAtPos(s, 0) == "H")
|
|
||||||
doAssert(runeSubStr(s, 0, 1) == "H")
|
|
||||||
doAssert(runeStrAtPos(s, 10) == ":")
|
|
||||||
doAssert(runeSubStr(s, 10, 1) == ":")
|
|
||||||
doAssert(runeStrAtPos(s, 9) == "«")
|
|
||||||
doAssert(runeSubStr(s, 9, 1) == "«")
|
|
||||||
doAssert(runeStrAtPos(s, 17) == "€")
|
|
||||||
doAssert(runeSubStr(s, 17, 1) == "€")
|
|
||||||
# echo runeStrAtPos(s, 18) # index error
|
|
||||||
|
|
||||||
doAssert(runeSubStr(s, 0) == "Hänsel ««: 10,00€")
|
|
||||||
doAssert(runeSubStr(s, -18) == "Hänsel ««: 10,00€")
|
|
||||||
doAssert(runeSubStr(s, 10) == ": 10,00€")
|
|
||||||
doAssert(runeSubStr(s, 18) == "")
|
|
||||||
doAssert(runeSubStr(s, 0, 10) == "Hänsel ««")
|
|
||||||
|
|
||||||
doAssert(runeSubStr(s, 12) == "10,00€")
|
|
||||||
doAssert(runeSubStr(s, -6) == "10,00€")
|
|
||||||
|
|
||||||
doAssert(runeSubStr(s, 12, 5) == "10,00")
|
|
||||||
doAssert(runeSubStr(s, 12, -1) == "10,00")
|
|
||||||
doAssert(runeSubStr(s, -6, 5) == "10,00")
|
|
||||||
doAssert(runeSubStr(s, -6, -1) == "10,00")
|
|
||||||
|
|
||||||
doAssert(runeSubStr(s, 0, 100) == "Hänsel ««: 10,00€")
|
|
||||||
doAssert(runeSubStr(s, -100, 100) == "Hänsel ««: 10,00€")
|
|
||||||
doAssert(runeSubStr(s, 0, -100) == "")
|
|
||||||
doAssert(runeSubStr(s, 100, -100) == "")
|
|
||||||
|
|
||||||
block splitTests:
|
|
||||||
let s = " this is an example "
|
|
||||||
let s2 = ":this;is;an:example;;"
|
|
||||||
let s3 = ":this×is×an:example××"
|
|
||||||
doAssert s.split() == @["", "this", "is", "an", "example", "", ""]
|
|
||||||
doAssert s2.split(seps = [':'.Rune, ';'.Rune]) == @["", "this", "is", "an",
|
|
||||||
"example", "", ""]
|
|
||||||
doAssert s3.split(seps = [':'.Rune, "×".asRune]) == @["", "this", "is",
|
|
||||||
"an", "example", "", ""]
|
|
||||||
doAssert s.split(maxsplit = 4) == @["", "this", "is", "an", "example "]
|
|
||||||
doAssert s.split(' '.Rune, maxsplit = 1) == @["", "this is an example "]
|
|
||||||
doAssert s3.split("×".runeAt(0)) == @[":this", "is", "an:example", "", ""]
|
|
||||||
|
|
||||||
block stripTests:
|
|
||||||
doAssert(strip("") == "")
|
|
||||||
doAssert(strip(" ") == "")
|
|
||||||
doAssert(strip("y") == "y")
|
|
||||||
doAssert(strip(" foofoofoo ") == "foofoofoo")
|
|
||||||
doAssert(strip("sfoofoofoos", runes = ['s'.Rune]) == "foofoofoo")
|
|
||||||
|
|
||||||
block:
|
|
||||||
let stripTestRunes = ['b'.Rune, 'a'.Rune, 'r'.Rune]
|
|
||||||
doAssert(strip("barfoofoofoobar", runes = stripTestRunes) == "foofoofoo")
|
|
||||||
doAssert(strip("sfoofoofoos", leading = false, runes = ['s'.Rune]) == "sfoofoofoo")
|
|
||||||
doAssert(strip("sfoofoofoos", trailing = false, runes = ['s'.Rune]) == "foofoofoos")
|
|
||||||
|
|
||||||
block:
|
|
||||||
let stripTestRunes = ["«".asRune, "»".asRune]
|
|
||||||
doAssert(strip("«TEXT»", runes = stripTestRunes) == "TEXT")
|
|
||||||
doAssert(strip("copyright©", leading = false, runes = ["©".asRune]) == "copyright")
|
|
||||||
doAssert(strip("¿Question?", trailing = false, runes = ["¿".asRune]) == "Question?")
|
|
||||||
doAssert(strip("×text×", leading = false, runes = ["×".asRune]) == "×text")
|
|
||||||
doAssert(strip("×text×", trailing = false, runes = ["×".asRune]) == "text×")
|
|
||||||
|
|
||||||
block repeatTests:
|
|
||||||
doAssert repeat('c'.Rune, 5) == "ccccc"
|
|
||||||
doAssert repeat("×".asRune, 5) == "×××××"
|
|
||||||
|
|
||||||
block alignTests:
|
|
||||||
doAssert align("abc", 4) == " abc"
|
|
||||||
doAssert align("a", 0) == "a"
|
|
||||||
doAssert align("1232", 6) == " 1232"
|
|
||||||
doAssert align("1232", 6, '#'.Rune) == "##1232"
|
|
||||||
doAssert align("1232", 6, "×".asRune) == "××1232"
|
|
||||||
doAssert alignLeft("abc", 4) == "abc "
|
|
||||||
doAssert alignLeft("a", 0) == "a"
|
|
||||||
doAssert alignLeft("1232", 6) == "1232 "
|
|
||||||
doAssert alignLeft("1232", 6, '#'.Rune) == "1232##"
|
|
||||||
doAssert alignLeft("1232", 6, "×".asRune) == "1232××"
|
|
||||||
|
|
||||||
block differentSizes:
|
|
||||||
# upper and lower variants have different number of bytes
|
|
||||||
doAssert toLower("AẞC") == "aßc"
|
|
||||||
doAssert toLower("ȺẞCD") == "ⱥßcd"
|
|
||||||
doAssert toUpper("ⱥbc") == "ȺBC"
|
|
||||||
doAssert toUpper("rsⱦuv") == "RSȾUV"
|
|
||||||
doAssert swapCase("ⱥbCd") == "ȺBcD"
|
|
||||||
doAssert swapCase("XyꟆaB") == "xYᶎAb"
|
|
||||||
doAssert swapCase("aᵹcᲈd") == "AꝽCꙊD"
|
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,3 @@ proc unidecode*(s: string): string =
|
||||||
var c = int(r)
|
var c = int(r)
|
||||||
if c <=% 127: add(result, chr(c))
|
if c <=% 127: add(result, chr(c))
|
||||||
elif c <% translationTable.len: add(result, translationTable[c-128])
|
elif c <% translationTable.len: add(result, translationTable[c-128])
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
#loadUnidecodeTable("lib/pure/unidecode/unidecode.dat")
|
|
||||||
doAssert unidecode("Äußerst") == "Ausserst"
|
|
||||||
doAssert unidecode("北京") == "Bei Jing "
|
|
||||||
|
|
|
||||||
285
lib/pure/uri.nim
285
lib/pure/uri.nim
|
|
@ -503,288 +503,3 @@ proc getDataUri*(data, mime: string, encoding = "utf-8"): string {.since: (1, 3)
|
||||||
runnableExamples: static: doAssert getDataUri("Nim", "text/plain") == "data:text/plain;charset=utf-8;base64,Tmlt"
|
runnableExamples: static: doAssert getDataUri("Nim", "text/plain") == "data:text/plain;charset=utf-8;base64,Tmlt"
|
||||||
assert encoding.len > 0 and mime.len > 0 # Must *not* be URL-Safe, see RFC-2397
|
assert encoding.len > 0 and mime.len > 0 # Must *not* be URL-Safe, see RFC-2397
|
||||||
result = "data:" & mime & ";charset=" & encoding & ";base64," & base64.encode(data)
|
result = "data:" & mime & ";charset=" & encoding & ";base64," & base64.encode(data)
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
block:
|
|
||||||
const test1 = "abc\L+def xyz"
|
|
||||||
doAssert encodeUrl(test1) == "abc%0A%2Bdef+xyz"
|
|
||||||
doAssert decodeUrl(encodeUrl(test1)) == test1
|
|
||||||
doAssert encodeUrl(test1, false) == "abc%0A%2Bdef%20xyz"
|
|
||||||
doAssert decodeUrl(encodeUrl(test1, false), false) == test1
|
|
||||||
doAssert decodeUrl(encodeUrl(test1)) == test1
|
|
||||||
|
|
||||||
block:
|
|
||||||
let str = "http://localhost"
|
|
||||||
let test = parseUri(str)
|
|
||||||
doAssert test.path == ""
|
|
||||||
|
|
||||||
block:
|
|
||||||
let str = "http://localhost/"
|
|
||||||
let test = parseUri(str)
|
|
||||||
doAssert test.path == "/"
|
|
||||||
|
|
||||||
block:
|
|
||||||
let str = "http://localhost:8080/test"
|
|
||||||
let test = parseUri(str)
|
|
||||||
doAssert test.scheme == "http"
|
|
||||||
doAssert test.port == "8080"
|
|
||||||
doAssert test.path == "/test"
|
|
||||||
doAssert test.hostname == "localhost"
|
|
||||||
doAssert($test == str)
|
|
||||||
|
|
||||||
block:
|
|
||||||
let str = "foo://username:password@example.com:8042/over/there" &
|
|
||||||
"/index.dtb?type=animal&name=narwhal#nose"
|
|
||||||
let test = parseUri(str)
|
|
||||||
doAssert test.scheme == "foo"
|
|
||||||
doAssert test.username == "username"
|
|
||||||
doAssert test.password == "password"
|
|
||||||
doAssert test.hostname == "example.com"
|
|
||||||
doAssert test.port == "8042"
|
|
||||||
doAssert test.path == "/over/there/index.dtb"
|
|
||||||
doAssert test.query == "type=animal&name=narwhal"
|
|
||||||
doAssert test.anchor == "nose"
|
|
||||||
doAssert($test == str)
|
|
||||||
|
|
||||||
block:
|
|
||||||
# IPv6 address
|
|
||||||
let str = "foo://[::1]:1234/bar?baz=true&qux#quux"
|
|
||||||
let uri = parseUri(str)
|
|
||||||
doAssert uri.scheme == "foo"
|
|
||||||
doAssert uri.hostname == "::1"
|
|
||||||
doAssert uri.port == "1234"
|
|
||||||
doAssert uri.path == "/bar"
|
|
||||||
doAssert uri.query == "baz=true&qux"
|
|
||||||
doAssert uri.anchor == "quux"
|
|
||||||
|
|
||||||
block:
|
|
||||||
let str = "urn:example:animal:ferret:nose"
|
|
||||||
let test = parseUri(str)
|
|
||||||
doAssert test.scheme == "urn"
|
|
||||||
doAssert test.path == "example:animal:ferret:nose"
|
|
||||||
doAssert($test == str)
|
|
||||||
|
|
||||||
block:
|
|
||||||
let str = "mailto:username@example.com?subject=Topic"
|
|
||||||
let test = parseUri(str)
|
|
||||||
doAssert test.scheme == "mailto"
|
|
||||||
doAssert test.username == "username"
|
|
||||||
doAssert test.hostname == "example.com"
|
|
||||||
doAssert test.query == "subject=Topic"
|
|
||||||
doAssert($test == str)
|
|
||||||
|
|
||||||
block:
|
|
||||||
let str = "magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
|
|
||||||
let test = parseUri(str)
|
|
||||||
doAssert test.scheme == "magnet"
|
|
||||||
doAssert test.query == "xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
|
|
||||||
doAssert($test == str)
|
|
||||||
|
|
||||||
block:
|
|
||||||
let str = "/test/foo/bar?q=2#asdf"
|
|
||||||
let test = parseUri(str)
|
|
||||||
doAssert test.scheme == ""
|
|
||||||
doAssert test.path == "/test/foo/bar"
|
|
||||||
doAssert test.query == "q=2"
|
|
||||||
doAssert test.anchor == "asdf"
|
|
||||||
doAssert($test == str)
|
|
||||||
|
|
||||||
block:
|
|
||||||
let str = "test/no/slash"
|
|
||||||
let test = parseUri(str)
|
|
||||||
doAssert test.path == "test/no/slash"
|
|
||||||
doAssert($test == str)
|
|
||||||
|
|
||||||
block:
|
|
||||||
let str = "//git@github.com:dom96/packages"
|
|
||||||
let test = parseUri(str)
|
|
||||||
doAssert test.scheme == ""
|
|
||||||
doAssert test.username == "git"
|
|
||||||
doAssert test.hostname == "github.com"
|
|
||||||
doAssert test.port == "dom96"
|
|
||||||
doAssert test.path == "/packages"
|
|
||||||
|
|
||||||
block:
|
|
||||||
let str = "file:///foo/bar/baz.txt"
|
|
||||||
let test = parseUri(str)
|
|
||||||
doAssert test.scheme == "file"
|
|
||||||
doAssert test.username == ""
|
|
||||||
doAssert test.hostname == ""
|
|
||||||
doAssert test.port == ""
|
|
||||||
doAssert test.path == "/foo/bar/baz.txt"
|
|
||||||
|
|
||||||
# Remove dot segments tests
|
|
||||||
block:
|
|
||||||
doAssert removeDotSegments("/foo/bar/baz") == "/foo/bar/baz"
|
|
||||||
|
|
||||||
# Combine tests
|
|
||||||
block:
|
|
||||||
let concat = combine(parseUri("http://google.com/foo/bar/"), parseUri("baz"))
|
|
||||||
doAssert concat.path == "/foo/bar/baz"
|
|
||||||
doAssert concat.hostname == "google.com"
|
|
||||||
doAssert concat.scheme == "http"
|
|
||||||
|
|
||||||
block:
|
|
||||||
let concat = combine(parseUri("http://google.com/foo"), parseUri("/baz"))
|
|
||||||
doAssert concat.path == "/baz"
|
|
||||||
doAssert concat.hostname == "google.com"
|
|
||||||
doAssert concat.scheme == "http"
|
|
||||||
|
|
||||||
block:
|
|
||||||
let concat = combine(parseUri("http://google.com/foo/test"), parseUri("bar"))
|
|
||||||
doAssert concat.path == "/foo/bar"
|
|
||||||
|
|
||||||
block:
|
|
||||||
let concat = combine(parseUri("http://google.com/foo/test"), parseUri("/bar"))
|
|
||||||
doAssert concat.path == "/bar"
|
|
||||||
|
|
||||||
block:
|
|
||||||
let concat = combine(parseUri("http://google.com/foo/test"), parseUri("bar"))
|
|
||||||
doAssert concat.path == "/foo/bar"
|
|
||||||
|
|
||||||
block:
|
|
||||||
let concat = combine(parseUri("http://google.com/foo/test/"), parseUri("bar"))
|
|
||||||
doAssert concat.path == "/foo/test/bar"
|
|
||||||
|
|
||||||
block:
|
|
||||||
let concat = combine(parseUri("http://google.com/foo/test/"), parseUri("bar/"))
|
|
||||||
doAssert concat.path == "/foo/test/bar/"
|
|
||||||
|
|
||||||
block:
|
|
||||||
let concat = combine(parseUri("http://google.com/foo/test/"), parseUri("bar/"),
|
|
||||||
parseUri("baz"))
|
|
||||||
doAssert concat.path == "/foo/test/bar/baz"
|
|
||||||
|
|
||||||
# `/` tests
|
|
||||||
block:
|
|
||||||
let test = parseUri("http://example.com/foo") / "bar/asd"
|
|
||||||
doAssert test.path == "/foo/bar/asd"
|
|
||||||
|
|
||||||
block:
|
|
||||||
let test = parseUri("http://example.com/foo/") / "/bar/asd"
|
|
||||||
doAssert test.path == "/foo/bar/asd"
|
|
||||||
|
|
||||||
# removeDotSegments tests
|
|
||||||
block:
|
|
||||||
# empty test
|
|
||||||
doAssert removeDotSegments("") == ""
|
|
||||||
|
|
||||||
# bug #3207
|
|
||||||
block:
|
|
||||||
doAssert parseUri("http://qq/1").combine(parseUri("https://qqq")).`$` == "https://qqq"
|
|
||||||
|
|
||||||
# bug #4959
|
|
||||||
block:
|
|
||||||
let foo = parseUri("http://example.com") / "/baz"
|
|
||||||
doAssert foo.path == "/baz"
|
|
||||||
|
|
||||||
# bug found on stream 13/10/17
|
|
||||||
block:
|
|
||||||
let foo = parseUri("http://localhost:9515") / "status"
|
|
||||||
doAssert $foo == "http://localhost:9515/status"
|
|
||||||
|
|
||||||
# bug #6649 #6652
|
|
||||||
block:
|
|
||||||
var foo = parseUri("http://example.com")
|
|
||||||
foo.hostname = "example.com"
|
|
||||||
foo.path = "baz"
|
|
||||||
doAssert $foo == "http://example.com/baz"
|
|
||||||
|
|
||||||
foo.hostname = "example.com/"
|
|
||||||
foo.path = "baz"
|
|
||||||
doAssert $foo == "http://example.com/baz"
|
|
||||||
|
|
||||||
foo.hostname = "example.com"
|
|
||||||
foo.path = "/baz"
|
|
||||||
doAssert $foo == "http://example.com/baz"
|
|
||||||
|
|
||||||
foo.hostname = "example.com/"
|
|
||||||
foo.path = "/baz"
|
|
||||||
doAssert $foo == "http://example.com/baz"
|
|
||||||
|
|
||||||
foo.hostname = "example.com/"
|
|
||||||
foo.port = "8000"
|
|
||||||
foo.path = "baz"
|
|
||||||
doAssert $foo == "http://example.com:8000/baz"
|
|
||||||
|
|
||||||
foo = parseUri("file:/dir/file")
|
|
||||||
foo.path = "relative"
|
|
||||||
doAssert $foo == "file:relative"
|
|
||||||
|
|
||||||
# isAbsolute tests
|
|
||||||
block:
|
|
||||||
doAssert "www.google.com".parseUri().isAbsolute() == false
|
|
||||||
doAssert "http://www.google.com".parseUri().isAbsolute() == true
|
|
||||||
doAssert "file:/dir/file".parseUri().isAbsolute() == true
|
|
||||||
doAssert "file://localhost/dir/file".parseUri().isAbsolute() == true
|
|
||||||
doAssert "urn:ISSN:1535-3613".parseUri().isAbsolute() == true
|
|
||||||
|
|
||||||
# path-relative URL *relative
|
|
||||||
doAssert "about".parseUri().isAbsolute == false
|
|
||||||
doAssert "about/staff.html".parseUri().isAbsolute == false
|
|
||||||
doAssert "about/staff.html?".parseUri().isAbsolute == false
|
|
||||||
doAssert "about/staff.html?parameters".parseUri().isAbsolute == false
|
|
||||||
|
|
||||||
# absolute-path-relative URL *relative
|
|
||||||
doAssert "/".parseUri().isAbsolute == false
|
|
||||||
doAssert "/about".parseUri().isAbsolute == false
|
|
||||||
doAssert "/about/staff.html".parseUri().isAbsolute == false
|
|
||||||
doAssert "/about/staff.html?".parseUri().isAbsolute == false
|
|
||||||
doAssert "/about/staff.html?parameters".parseUri().isAbsolute == false
|
|
||||||
|
|
||||||
# scheme-relative URL *relative
|
|
||||||
doAssert "//username:password@example.com:8888".parseUri().isAbsolute == false
|
|
||||||
doAssert "//username@example.com".parseUri().isAbsolute == false
|
|
||||||
doAssert "//example.com".parseUri().isAbsolute == false
|
|
||||||
doAssert "//example.com/".parseUri().isAbsolute == false
|
|
||||||
doAssert "//example.com/about".parseUri().isAbsolute == false
|
|
||||||
doAssert "//example.com/about/staff.html".parseUri().isAbsolute == false
|
|
||||||
doAssert "//example.com/about/staff.html?".parseUri().isAbsolute == false
|
|
||||||
doAssert "//example.com/about/staff.html?parameters".parseUri().isAbsolute == false
|
|
||||||
|
|
||||||
# absolute URL *absolute
|
|
||||||
doAssert "https://username:password@example.com:8888".parseUri().isAbsolute == true
|
|
||||||
doAssert "https://username@example.com".parseUri().isAbsolute == true
|
|
||||||
doAssert "https://example.com".parseUri().isAbsolute == true
|
|
||||||
doAssert "https://example.com/".parseUri().isAbsolute == true
|
|
||||||
doAssert "https://example.com/about".parseUri().isAbsolute == true
|
|
||||||
doAssert "https://example.com/about/staff.html".parseUri().isAbsolute == true
|
|
||||||
doAssert "https://example.com/about/staff.html?".parseUri().isAbsolute == true
|
|
||||||
doAssert "https://example.com/about/staff.html?parameters".parseUri().isAbsolute == true
|
|
||||||
|
|
||||||
# encodeQuery tests
|
|
||||||
block:
|
|
||||||
doAssert encodeQuery({:}) == ""
|
|
||||||
doAssert encodeQuery({"foo": "bar"}) == "foo=bar"
|
|
||||||
doAssert encodeQuery({"foo": "bar & baz"}) == "foo=bar+%26+baz"
|
|
||||||
doAssert encodeQuery({"foo": "bar & baz"}, usePlus = false) == "foo=bar%20%26%20baz"
|
|
||||||
doAssert encodeQuery({"foo": ""}) == "foo"
|
|
||||||
doAssert encodeQuery({"foo": ""}, omitEq = false) == "foo="
|
|
||||||
doAssert encodeQuery({"a": "1", "b": "", "c": "3"}) == "a=1&b&c=3"
|
|
||||||
doAssert encodeQuery({"a": "1", "b": "", "c": "3"}, omitEq = false) == "a=1&b=&c=3"
|
|
||||||
|
|
||||||
block:
|
|
||||||
var foo = parseUri("http://example.com") / "foo" ? {"bar": "1", "baz": "qux"}
|
|
||||||
var foo1 = parseUri("http://example.com/foo?bar=1&baz=qux")
|
|
||||||
doAssert foo == foo1
|
|
||||||
|
|
||||||
block:
|
|
||||||
var foo = parseUri("http://example.com") / "foo" ? {"do": "do", "bar": ""}
|
|
||||||
var foo1 = parseUri("http://example.com/foo?do=do&bar")
|
|
||||||
doAssert foo == foo1
|
|
||||||
|
|
||||||
block dataUriBase64:
|
|
||||||
doAssert getDataUri("", "text/plain") == "data:text/plain;charset=utf-8;base64,"
|
|
||||||
doAssert getDataUri(" ", "text/plain") == "data:text/plain;charset=utf-8;base64,IA=="
|
|
||||||
doAssert getDataUri("c\xf7>", "text/plain") == "data:text/plain;charset=utf-8;base64,Y/c+"
|
|
||||||
doAssert getDataUri("Hello World", "text/plain") == "data:text/plain;charset=utf-8;base64,SGVsbG8gV29ybGQ="
|
|
||||||
doAssert getDataUri("leasure.", "text/plain") == "data:text/plain;charset=utf-8;base64,bGVhc3VyZS4="
|
|
||||||
doAssert getDataUri("""!@#$%^&*()_+""", "text/plain") == "data:text/plain;charset=utf-8;base64,IUAjJCVeJiooKV8r"
|
|
||||||
doAssert(getDataUri("the quick brown dog jumps over the lazy fox", "text/plain") ==
|
|
||||||
"data:text/plain;charset=utf-8;base64,dGhlIHF1aWNrIGJyb3duIGRvZyBqdW1wcyBvdmVyIHRoZSBsYXp5IGZveA==")
|
|
||||||
doAssert(getDataUri("""The present is theirs
|
|
||||||
The future, for which I really worked, is mine.""", "text/plain") ==
|
|
||||||
"data:text/plain;charset=utf-8;base64,VGhlIHByZXNlbnQgaXMgdGhlaXJzCiAgICAgIFRoZSBmdXR1cmUsIGZvciB3aGljaCBJIHJlYWxseSB3b3JrZWQsIGlzIG1pbmUu")
|
|
||||||
|
|
||||||
echo("All good!")
|
|
||||||
|
|
|
||||||
|
|
@ -68,22 +68,3 @@ macro enumerate*(x: ForLoopStmt): untyped {.since: (1, 3).} =
|
||||||
result.add newFor
|
result.add newFor
|
||||||
# now wrap the whole macro in a block to create a new scope
|
# now wrap the whole macro in a block to create a new scope
|
||||||
result = newBlockStmt(result)
|
result = newBlockStmt(result)
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
let a = @[1, 3, 5, 7]
|
|
||||||
|
|
||||||
block:
|
|
||||||
var res: seq[(int, int)]
|
|
||||||
for i, x in enumerate(a):
|
|
||||||
res.add (i, x)
|
|
||||||
assert res == @[(0, 1), (1, 3), (2, 5), (3, 7)]
|
|
||||||
block:
|
|
||||||
var res: seq[(int, int)]
|
|
||||||
for (i, x) in enumerate(a.items):
|
|
||||||
res.add (i, x)
|
|
||||||
assert res == @[(0, 1), (1, 3), (2, 5), (3, 7)]
|
|
||||||
block:
|
|
||||||
var res: seq[(int, int)]
|
|
||||||
for i, x in enumerate(3, a):
|
|
||||||
res.add (i, x)
|
|
||||||
assert res == @[(3, 1), (4, 3), (5, 5), (6, 7)]
|
|
||||||
|
|
|
||||||
|
|
@ -152,19 +152,3 @@ proc high*(typ: typedesc[MonoTime]): MonoTime =
|
||||||
proc low*(typ: typedesc[MonoTime]): MonoTime =
|
proc low*(typ: typedesc[MonoTime]): MonoTime =
|
||||||
## Returns the lowest representable `MonoTime`.
|
## Returns the lowest representable `MonoTime`.
|
||||||
MonoTime(ticks: low(int64))
|
MonoTime(ticks: low(int64))
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
let d = initDuration(nanoseconds = 10)
|
|
||||||
let t1 = getMonoTime()
|
|
||||||
let t2 = t1 + d
|
|
||||||
|
|
||||||
doAssert t2 - t1 == d
|
|
||||||
doAssert t1 == t1
|
|
||||||
doAssert t1 != t2
|
|
||||||
doAssert t2 - d == t1
|
|
||||||
doAssert t1 < t2
|
|
||||||
doAssert t1 <= t2
|
|
||||||
doAssert t1 <= t1
|
|
||||||
doAssert not(t2 < t1)
|
|
||||||
doAssert t1 < high(MonoTime)
|
|
||||||
doAssert low(MonoTime) < t1
|
|
||||||
|
|
|
||||||
|
|
@ -267,16 +267,3 @@ proc `==`*(a, b: SecureHash): bool =
|
||||||
assert a == c
|
assert a == c
|
||||||
# Not a constant-time comparison, but that's acceptable in this context
|
# Not a constant-time comparison, but that's acceptable in this context
|
||||||
Sha1Digest(a) == Sha1Digest(b)
|
Sha1Digest(a) == Sha1Digest(b)
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
let hash1 = secureHash("a93tgj0p34jagp9[agjp98ajrhp9aej]")
|
|
||||||
doAssert hash1 == hash1
|
|
||||||
doAssert parseSecureHash($hash1) == hash1
|
|
||||||
|
|
||||||
template checkVector(s, exp: string) =
|
|
||||||
doAssert secureHash(s) == parseSecureHash(exp)
|
|
||||||
|
|
||||||
checkVector("", "da39a3ee5e6b4b0d3255bfef95601890afd80709")
|
|
||||||
checkVector("abc", "a9993e364706816aba3e25717850c26c9cd0d89d")
|
|
||||||
checkVector("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
|
||||||
"84983e441c3bd26ebaae4aa1f95129e5e54670f1")
|
|
||||||
|
|
|
||||||
|
|
@ -16,3 +16,100 @@ proc test() =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
test()
|
test()
|
||||||
|
|
||||||
|
block:
|
||||||
|
# Tests for lowerBound
|
||||||
|
var arr = @[1, 2, 3, 5, 6, 7, 8, 9]
|
||||||
|
assert arr.lowerBound(0) == 0
|
||||||
|
assert arr.lowerBound(4) == 3
|
||||||
|
assert arr.lowerBound(5) == 3
|
||||||
|
assert arr.lowerBound(10) == 8
|
||||||
|
arr = @[1, 5, 10]
|
||||||
|
assert arr.lowerBound(4) == 1
|
||||||
|
assert arr.lowerBound(5) == 1
|
||||||
|
assert arr.lowerBound(6) == 2
|
||||||
|
# Tests for isSorted
|
||||||
|
var srt1 = [1, 2, 3, 4, 4, 4, 4, 5]
|
||||||
|
var srt2 = ["iello", "hello"]
|
||||||
|
var srt3 = [1.0, 1.0, 1.0]
|
||||||
|
var srt4: seq[int]
|
||||||
|
assert srt1.isSorted(cmp) == true
|
||||||
|
assert srt2.isSorted(cmp) == false
|
||||||
|
assert srt3.isSorted(cmp) == true
|
||||||
|
assert srt4.isSorted(cmp) == true
|
||||||
|
var srtseq = newSeq[int]()
|
||||||
|
assert srtseq.isSorted(cmp) == true
|
||||||
|
# Tests for reversed
|
||||||
|
var arr1 = @[0, 1, 2, 3, 4]
|
||||||
|
assert arr1.reversed() == @[4, 3, 2, 1, 0]
|
||||||
|
for i in 0 .. high(arr1):
|
||||||
|
assert arr1.reversed(0, i) == arr1.reversed()[high(arr1) - i .. high(arr1)]
|
||||||
|
assert arr1.reversed(i, high(arr1)) == arr1.reversed()[0 .. high(arr1) - i]
|
||||||
|
|
||||||
|
block:
|
||||||
|
var list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
|
let list2 = list.rotatedLeft(1 ..< 9, 3)
|
||||||
|
let expected = [0, 4, 5, 6, 7, 8, 1, 2, 3, 9, 10]
|
||||||
|
|
||||||
|
doAssert list.rotateLeft(1 ..< 9, 3) == 6
|
||||||
|
doAssert list == expected
|
||||||
|
doAssert list2 == @expected
|
||||||
|
|
||||||
|
var s0, s1, s2, s3, s4, s5 = "xxxabcdefgxxx"
|
||||||
|
|
||||||
|
doAssert s0.rotateLeft(3 ..< 10, 3) == 7
|
||||||
|
doAssert s0 == "xxxdefgabcxxx"
|
||||||
|
doAssert s1.rotateLeft(3 ..< 10, 2) == 8
|
||||||
|
doAssert s1 == "xxxcdefgabxxx"
|
||||||
|
doAssert s2.rotateLeft(3 ..< 10, 4) == 6
|
||||||
|
doAssert s2 == "xxxefgabcdxxx"
|
||||||
|
doAssert s3.rotateLeft(3 ..< 10, -3) == 6
|
||||||
|
doAssert s3 == "xxxefgabcdxxx"
|
||||||
|
doAssert s4.rotateLeft(3 ..< 10, -10) == 6
|
||||||
|
doAssert s4 == "xxxefgabcdxxx"
|
||||||
|
doAssert s5.rotateLeft(3 ..< 10, 11) == 6
|
||||||
|
doAssert s5 == "xxxefgabcdxxx"
|
||||||
|
|
||||||
|
block product:
|
||||||
|
doAssert product(newSeq[seq[int]]()) == newSeq[seq[int]](), "empty input"
|
||||||
|
doAssert product(@[newSeq[int](), @[], @[]]) == newSeq[seq[int]](), "bit more empty input"
|
||||||
|
doAssert product(@[@[1, 2]]) == @[@[1, 2]], "a simple case of one element"
|
||||||
|
doAssert product(@[@[1, 2], @[3, 4]]) == @[@[2, 4], @[1, 4], @[2, 3], @[1,
|
||||||
|
3]], "two elements"
|
||||||
|
doAssert product(@[@[1, 2], @[3, 4], @[5, 6]]) == @[@[2, 4, 6], @[1, 4, 6],
|
||||||
|
@[2, 3, 6], @[1, 3, 6], @[2, 4, 5], @[1, 4, 5], @[2, 3, 5], @[1, 3, 5]], "three elements"
|
||||||
|
doAssert product(@[@[1, 2], @[]]) == newSeq[seq[int]](), "two elements, but one empty"
|
||||||
|
|
||||||
|
block lowerBound:
|
||||||
|
doAssert lowerBound([1, 2, 4], 3, system.cmp[int]) == 2
|
||||||
|
doAssert lowerBound([1, 2, 2, 3], 4, system.cmp[int]) == 4
|
||||||
|
doAssert lowerBound([1, 2, 3, 10], 11) == 4
|
||||||
|
|
||||||
|
block upperBound:
|
||||||
|
doAssert upperBound([1, 2, 4], 3, system.cmp[int]) == 2
|
||||||
|
doAssert upperBound([1, 2, 2, 3], 3, system.cmp[int]) == 4
|
||||||
|
doAssert upperBound([1, 2, 3, 5], 3) == 3
|
||||||
|
|
||||||
|
block fillEmptySeq:
|
||||||
|
var s = newSeq[int]()
|
||||||
|
s.fill(0)
|
||||||
|
|
||||||
|
block testBinarySearch:
|
||||||
|
var noData: seq[int]
|
||||||
|
doAssert binarySearch(noData, 7) == -1
|
||||||
|
let oneData = @[1]
|
||||||
|
doAssert binarySearch(oneData, 1) == 0
|
||||||
|
doAssert binarySearch(onedata, 7) == -1
|
||||||
|
let someData = @[1, 3, 4, 7]
|
||||||
|
doAssert binarySearch(someData, 1) == 0
|
||||||
|
doAssert binarySearch(somedata, 7) == 3
|
||||||
|
doAssert binarySearch(someData, -1) == -1
|
||||||
|
doAssert binarySearch(someData, 5) == -1
|
||||||
|
doAssert binarySearch(someData, 13) == -1
|
||||||
|
let moreData = @[1, 3, 5, 7, 4711]
|
||||||
|
doAssert binarySearch(moreData, -1) == -1
|
||||||
|
doAssert binarySearch(moreData, 1) == 0
|
||||||
|
doAssert binarySearch(moreData, 5) == 2
|
||||||
|
doAssert binarySearch(moreData, 6) == -1
|
||||||
|
doAssert binarySearch(moreData, 4711) == 4
|
||||||
|
doAssert binarySearch(moreData, 4712) == -1
|
||||||
|
|
|
||||||
15
tests/stdlib/tcookies.nim
Normal file
15
tests/stdlib/tcookies.nim
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import cookies, times, strtabs
|
||||||
|
|
||||||
|
let expire = fromUnix(0) + 1.seconds
|
||||||
|
|
||||||
|
let theCookies = [
|
||||||
|
setCookie("test", "value", expire),
|
||||||
|
setCookie("test", "value", expire.local),
|
||||||
|
setCookie("test", "value", expire.utc)
|
||||||
|
]
|
||||||
|
let expected = "Set-Cookie: test=value; Expires=Thu, 01 Jan 1970 00:00:01 GMT"
|
||||||
|
doAssert theCookies == [expected, expected, expected]
|
||||||
|
|
||||||
|
let table = parseCookies("uid=1; kp=2")
|
||||||
|
doAssert table["uid"] == "1"
|
||||||
|
doAssert table["kp"] == "2"
|
||||||
61
tests/stdlib/tcritbits.nim
Normal file
61
tests/stdlib/tcritbits.nim
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
import sequtils, critbits
|
||||||
|
|
||||||
|
|
||||||
|
var r: CritBitTree[void]
|
||||||
|
r.incl "abc"
|
||||||
|
r.incl "xyz"
|
||||||
|
r.incl "def"
|
||||||
|
r.incl "definition"
|
||||||
|
r.incl "prefix"
|
||||||
|
r.incl "foo"
|
||||||
|
|
||||||
|
doAssert r.contains"def"
|
||||||
|
|
||||||
|
r.excl "def"
|
||||||
|
assert r.missingOrExcl("foo") == false
|
||||||
|
assert "foo" notin toSeq(r.items)
|
||||||
|
|
||||||
|
assert r.missingOrExcl("foo") == true
|
||||||
|
|
||||||
|
assert toSeq(r.items) == @["abc", "definition", "prefix", "xyz"]
|
||||||
|
|
||||||
|
assert toSeq(r.itemsWithPrefix("de")) == @["definition"]
|
||||||
|
var c = CritBitTree[int]()
|
||||||
|
|
||||||
|
c.inc("a")
|
||||||
|
assert c["a"] == 1
|
||||||
|
|
||||||
|
c.inc("a", 4)
|
||||||
|
assert c["a"] == 5
|
||||||
|
|
||||||
|
c.inc("a", -5)
|
||||||
|
assert c["a"] == 0
|
||||||
|
|
||||||
|
c.inc("b", 2)
|
||||||
|
assert c["b"] == 2
|
||||||
|
|
||||||
|
c.inc("c", 3)
|
||||||
|
assert c["c"] == 3
|
||||||
|
|
||||||
|
c.inc("a", 1)
|
||||||
|
assert c["a"] == 1
|
||||||
|
|
||||||
|
var cf = CritBitTree[float]()
|
||||||
|
|
||||||
|
cf.incl("a", 1.0)
|
||||||
|
assert cf["a"] == 1.0
|
||||||
|
|
||||||
|
cf.incl("b", 2.0)
|
||||||
|
assert cf["b"] == 2.0
|
||||||
|
|
||||||
|
cf.incl("c", 3.0)
|
||||||
|
assert cf["c"] == 3.0
|
||||||
|
|
||||||
|
assert cf.len == 3
|
||||||
|
cf.excl("c")
|
||||||
|
assert cf.len == 2
|
||||||
|
|
||||||
|
var cb: CritBitTree[string]
|
||||||
|
cb.incl("help", "help")
|
||||||
|
for k in cb.keysWithPrefix("helpp"):
|
||||||
|
doAssert false, "there is no prefix helpp"
|
||||||
19
tests/stdlib/tenumerate.nim
Normal file
19
tests/stdlib/tenumerate.nim
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
import std/enumerate
|
||||||
|
|
||||||
|
let a = @[1, 3, 5, 7]
|
||||||
|
|
||||||
|
block:
|
||||||
|
var res: seq[(int, int)]
|
||||||
|
for i, x in enumerate(a):
|
||||||
|
res.add (i, x)
|
||||||
|
assert res == @[(0, 1), (1, 3), (2, 5), (3, 7)]
|
||||||
|
block:
|
||||||
|
var res: seq[(int, int)]
|
||||||
|
for (i, x) in enumerate(a.items):
|
||||||
|
res.add (i, x)
|
||||||
|
assert res == @[(0, 1), (1, 3), (2, 5), (3, 7)]
|
||||||
|
block:
|
||||||
|
var res: seq[(int, int)]
|
||||||
|
for i, x in enumerate(3, a):
|
||||||
|
res.add (i, x)
|
||||||
|
assert res == @[(3, 1), (4, 3), (5, 5), (6, 7)]
|
||||||
8
tests/stdlib/tfenv.nim
Normal file
8
tests/stdlib/tfenv.nim
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import fenv
|
||||||
|
|
||||||
|
|
||||||
|
func is_significant(x: float): bool =
|
||||||
|
if x > minimumPositiveValue(float) and x < maximumPositiveValue(float): true
|
||||||
|
else: false
|
||||||
|
|
||||||
|
doAssert is_significant(10.0)
|
||||||
|
|
@ -1,34 +1,71 @@
|
||||||
|
import hashes
|
||||||
|
|
||||||
discard """
|
block hashes:
|
||||||
output: '''
|
block hashing:
|
||||||
[Suite] hashes
|
var dummy = 0.0
|
||||||
|
doAssert hash(dummy) == hash(-dummy)
|
||||||
|
|
||||||
[Suite] hashing
|
# "VM and runtime should make the same hash value (hashIdentity)"
|
||||||
|
block:
|
||||||
|
const hi123 = hashIdentity(123)
|
||||||
|
doAssert hashIdentity(123) == hi123
|
||||||
|
|
||||||
'''
|
# "VM and runtime should make the same hash value (hashWangYi1)"
|
||||||
"""
|
block:
|
||||||
|
const wy123 = hashWangYi1(123)
|
||||||
|
doAssert hashWangYi1(123) == wy123
|
||||||
|
|
||||||
import unittest, hashes
|
# "hashIdentity value incorrect at 456"
|
||||||
|
block:
|
||||||
|
doAssert hashIdentity(456) == 456
|
||||||
|
|
||||||
suite "hashes":
|
# "hashWangYi1 value incorrect at 456"
|
||||||
suite "hashing":
|
block:
|
||||||
test "0.0 and -0.0 should have the same hash value":
|
when Hash.sizeof < 8:
|
||||||
var dummy = 0.0
|
doAssert hashWangYi1(456) == 1293320666
|
||||||
check hash(dummy) == hash(-dummy)
|
else:
|
||||||
|
doAssert hashWangYi1(456) == -6421749900419628582
|
||||||
|
|
||||||
test "VM and runtime should make the same hash value (hashIdentity)":
|
block empty:
|
||||||
const hi123 = hashIdentity(123)
|
var
|
||||||
check hashIdentity(123) == hi123
|
a = ""
|
||||||
|
b = newSeq[char]()
|
||||||
|
c = newSeq[int]()
|
||||||
|
d = cstring""
|
||||||
|
e = "abcd"
|
||||||
|
doAssert hash(a) == 0
|
||||||
|
doAssert hash(b) == 0
|
||||||
|
doAssert hash(c) == 0
|
||||||
|
doAssert hash(d) == 0
|
||||||
|
doAssert hashIgnoreCase(a) == 0
|
||||||
|
doAssert hashIgnoreStyle(a) == 0
|
||||||
|
doAssert hash(e, 3, 2) == 0
|
||||||
|
|
||||||
test "VM and runtime should make the same hash value (hashWangYi1)":
|
block sameButDifferent:
|
||||||
const wy123 = hashWangYi1(123)
|
doAssert hash("aa bb aaaa1234") == hash("aa bb aaaa1234", 0, 13)
|
||||||
check hashWangYi1(123) == wy123
|
doAssert hash("aa bb aaaa1234") == hash(cstring"aa bb aaaa1234")
|
||||||
|
doAssert hashIgnoreCase("aA bb aAAa1234") == hashIgnoreCase("aa bb aaaa1234")
|
||||||
|
doAssert hashIgnoreStyle("aa_bb_AAaa1234") == hashIgnoreCase("aaBBAAAa1234")
|
||||||
|
|
||||||
test "hashIdentity value incorrect at 456":
|
block smallSize: # no multibyte hashing
|
||||||
check hashIdentity(456) == 456
|
let
|
||||||
|
xx = @['H', 'i']
|
||||||
|
ii = @[72'u8, 105]
|
||||||
|
ss = "Hi"
|
||||||
|
doAssert hash(xx) == hash(ii)
|
||||||
|
doAssert hash(xx) == hash(ss)
|
||||||
|
doAssert hash(xx) == hash(xx, 0, xx.high)
|
||||||
|
doAssert hash(ss) == hash(ss, 0, ss.high)
|
||||||
|
|
||||||
test "hashWangYi1 value incorrect at 456":
|
block largeSize: # longer than 4 characters
|
||||||
when Hash.sizeof < 8:
|
let
|
||||||
check hashWangYi1(456) == 1293320666
|
xx = @['H', 'e', 'l', 'l', 'o']
|
||||||
else:
|
xxl = @['H', 'e', 'l', 'l', 'o', 'w', 'e', 'e', 'n', 's']
|
||||||
check hashWangYi1(456) == -6421749900419628582
|
ssl = "Helloweens"
|
||||||
|
doAssert hash(xxl) == hash(ssl)
|
||||||
|
doAssert hash(xxl) == hash(xxl, 0, xxl.high)
|
||||||
|
doAssert hash(ssl) == hash(ssl, 0, ssl.high)
|
||||||
|
doAssert hash(xx) == hash(xxl, 0, 4)
|
||||||
|
doAssert hash(xx) == hash(ssl, 0, 4)
|
||||||
|
doAssert hash(xx, 0, 3) == hash(xxl, 0, 3)
|
||||||
|
doAssert hash(xx, 0, 3) == hash(ssl, 0, 3)
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,12 @@
|
||||||
discard """
|
|
||||||
output: "[Suite] httpcore"
|
|
||||||
"""
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import httpcore, strutils
|
import httpcore, strutils
|
||||||
|
|
||||||
suite "httpcore":
|
block:
|
||||||
|
block HttpCode:
|
||||||
test "HttpCode":
|
|
||||||
assert $Http418 == "418 I'm a teapot"
|
assert $Http418 == "418 I'm a teapot"
|
||||||
assert Http418.is4xx() == true
|
assert Http418.is4xx() == true
|
||||||
assert Http418.is2xx() == false
|
assert Http418.is2xx() == false
|
||||||
|
|
||||||
test "headers":
|
block headers:
|
||||||
var h = newHttpHeaders()
|
var h = newHttpHeaders()
|
||||||
assert h.len == 0
|
assert h.len == 0
|
||||||
h.add("Cookie", "foo")
|
h.add("Cookie", "foo")
|
||||||
|
|
@ -35,7 +28,7 @@ suite "httpcore":
|
||||||
|
|
||||||
assert seq[string](h1["a"]).join(",") == "1,2,3"
|
assert seq[string](h1["a"]).join(",") == "1,2,3"
|
||||||
|
|
||||||
test "test cookies with comma":
|
block test_cookies_with_comma:
|
||||||
doAssert parseHeader("cookie: foo, bar") == ("cookie", @["foo, bar"])
|
doAssert parseHeader("cookie: foo, bar") == ("cookie", @["foo, bar"])
|
||||||
doAssert parseHeader("cookie: foo, bar, prologue") == ("cookie", @["foo, bar, prologue"])
|
doAssert parseHeader("cookie: foo, bar, prologue") == ("cookie", @["foo, bar, prologue"])
|
||||||
doAssert parseHeader("cookie: foo, bar, prologue, starlight") == ("cookie", @["foo, bar, prologue, starlight"])
|
doAssert parseHeader("cookie: foo, bar, prologue, starlight") == ("cookie", @["foo, bar, prologue, starlight"])
|
||||||
|
|
@ -52,7 +45,7 @@ suite "httpcore":
|
||||||
doAssert parseHeader("Accept: foo, bar, prologue") == (key: "Accept", value: @["foo", "bar", "prologue"])
|
doAssert parseHeader("Accept: foo, bar, prologue") == (key: "Accept", value: @["foo", "bar", "prologue"])
|
||||||
doAssert parseHeader("Accept: foo, bar, prologue, starlight") == (key: "Accept", value: @["foo", "bar", "prologue", "starlight"])
|
doAssert parseHeader("Accept: foo, bar, prologue, starlight") == (key: "Accept", value: @["foo", "bar", "prologue", "starlight"])
|
||||||
|
|
||||||
test "add empty sequence to HTTP headers":
|
block add_empty_sequence_to_HTTP_headers:
|
||||||
block:
|
block:
|
||||||
var headers = newHttpHeaders()
|
var headers = newHttpHeaders()
|
||||||
headers["empty"] = @[]
|
headers["empty"] = @[]
|
||||||
|
|
@ -78,3 +71,28 @@ suite "httpcore":
|
||||||
headers["existing"] = @[]
|
headers["existing"] = @[]
|
||||||
headers["existing"] = @["true"]
|
headers["existing"] = @["true"]
|
||||||
doAssert headers.hasKey("existing")
|
doAssert headers.hasKey("existing")
|
||||||
|
|
||||||
|
block:
|
||||||
|
var test = newHttpHeaders()
|
||||||
|
test["Connection"] = @["Upgrade", "Close"]
|
||||||
|
doAssert test["Connection", 0] == "Upgrade"
|
||||||
|
doAssert test["Connection", 1] == "Close"
|
||||||
|
test.add("Connection", "Test")
|
||||||
|
doAssert test["Connection", 2] == "Test"
|
||||||
|
doAssert "upgrade" in test["Connection"]
|
||||||
|
|
||||||
|
# Bug #5344.
|
||||||
|
doAssert parseHeader("foobar: ") == ("foobar", @[""])
|
||||||
|
let (key, value) = parseHeader("foobar: ")
|
||||||
|
test = newHttpHeaders()
|
||||||
|
test[key] = value
|
||||||
|
doAssert test["foobar"] == ""
|
||||||
|
|
||||||
|
doAssert parseHeader("foobar:") == ("foobar", @[""])
|
||||||
|
|
||||||
|
block: # test title case
|
||||||
|
var testTitleCase = newHttpHeaders(titleCase=true)
|
||||||
|
testTitleCase.add("content-length", "1")
|
||||||
|
doAssert testTitleCase.hasKey("Content-Length")
|
||||||
|
for key, val in testTitleCase:
|
||||||
|
doAssert key == "Content-Length"
|
||||||
|
|
|
||||||
|
|
@ -145,3 +145,129 @@ suite "^":
|
||||||
check: compiles(5.5 ^ 2.uint)
|
check: compiles(5.5 ^ 2.uint)
|
||||||
check: compiles(5.5 ^ 2.uint8)
|
check: compiles(5.5 ^ 2.uint8)
|
||||||
check: not compiles(5.5 ^ 2.2)
|
check: not compiles(5.5 ^ 2.2)
|
||||||
|
|
||||||
|
block:
|
||||||
|
when not defined(js):
|
||||||
|
# Check for no side effect annotation
|
||||||
|
proc mySqrt(num: float): float {.noSideEffect.} =
|
||||||
|
return sqrt(num)
|
||||||
|
|
||||||
|
# check gamma function
|
||||||
|
assert(gamma(5.0) == 24.0) # 4!
|
||||||
|
assert(lgamma(1.0) == 0.0) # ln(1.0) == 0.0
|
||||||
|
assert(erf(6.0) > erf(5.0))
|
||||||
|
assert(erfc(6.0) < erfc(5.0))
|
||||||
|
|
||||||
|
|
||||||
|
# Function for approximate comparison of floats
|
||||||
|
proc `==~`(x, y: float): bool = (abs(x-y) < 1e-9)
|
||||||
|
|
||||||
|
block: # prod
|
||||||
|
doAssert prod([1, 2, 3, 4]) == 24
|
||||||
|
doAssert prod([1.5, 3.4]) == 5.1
|
||||||
|
let x: seq[float] = @[]
|
||||||
|
doAssert prod(x) == 1.0
|
||||||
|
|
||||||
|
block: # round() tests
|
||||||
|
# Round to 0 decimal places
|
||||||
|
doAssert round(54.652) ==~ 55.0
|
||||||
|
doAssert round(54.352) ==~ 54.0
|
||||||
|
doAssert round(-54.652) ==~ -55.0
|
||||||
|
doAssert round(-54.352) ==~ -54.0
|
||||||
|
doAssert round(0.0) ==~ 0.0
|
||||||
|
|
||||||
|
block: # splitDecimal() tests
|
||||||
|
doAssert splitDecimal(54.674).intpart ==~ 54.0
|
||||||
|
doAssert splitDecimal(54.674).floatpart ==~ 0.674
|
||||||
|
doAssert splitDecimal(-693.4356).intpart ==~ -693.0
|
||||||
|
doAssert splitDecimal(-693.4356).floatpart ==~ -0.4356
|
||||||
|
doAssert splitDecimal(0.0).intpart ==~ 0.0
|
||||||
|
doAssert splitDecimal(0.0).floatpart ==~ 0.0
|
||||||
|
|
||||||
|
block: # trunc tests for vcc
|
||||||
|
doAssert(trunc(-1.1) == -1)
|
||||||
|
doAssert(trunc(1.1) == 1)
|
||||||
|
doAssert(trunc(-0.1) == -0)
|
||||||
|
doAssert(trunc(0.1) == 0)
|
||||||
|
|
||||||
|
#special case
|
||||||
|
doAssert(classify(trunc(1e1000000)) == fcInf)
|
||||||
|
doAssert(classify(trunc(-1e1000000)) == fcNegInf)
|
||||||
|
doAssert(classify(trunc(0.0/0.0)) == fcNan)
|
||||||
|
doAssert(classify(trunc(0.0)) == fcZero)
|
||||||
|
|
||||||
|
#trick the compiler to produce signed zero
|
||||||
|
let
|
||||||
|
f_neg_one = -1.0
|
||||||
|
f_zero = 0.0
|
||||||
|
f_nan = f_zero / f_zero
|
||||||
|
|
||||||
|
doAssert(classify(trunc(f_neg_one*f_zero)) == fcNegZero)
|
||||||
|
|
||||||
|
doAssert(trunc(-1.1'f32) == -1)
|
||||||
|
doAssert(trunc(1.1'f32) == 1)
|
||||||
|
doAssert(trunc(-0.1'f32) == -0)
|
||||||
|
doAssert(trunc(0.1'f32) == 0)
|
||||||
|
doAssert(classify(trunc(1e1000000'f32)) == fcInf)
|
||||||
|
doAssert(classify(trunc(-1e1000000'f32)) == fcNegInf)
|
||||||
|
doAssert(classify(trunc(f_nan.float32)) == fcNan)
|
||||||
|
doAssert(classify(trunc(0.0'f32)) == fcZero)
|
||||||
|
|
||||||
|
block: # sgn() tests
|
||||||
|
assert sgn(1'i8) == 1
|
||||||
|
assert sgn(1'i16) == 1
|
||||||
|
assert sgn(1'i32) == 1
|
||||||
|
assert sgn(1'i64) == 1
|
||||||
|
assert sgn(1'u8) == 1
|
||||||
|
assert sgn(1'u16) == 1
|
||||||
|
assert sgn(1'u32) == 1
|
||||||
|
assert sgn(1'u64) == 1
|
||||||
|
assert sgn(-12342.8844'f32) == -1
|
||||||
|
assert sgn(123.9834'f64) == 1
|
||||||
|
assert sgn(0'i32) == 0
|
||||||
|
assert sgn(0'f32) == 0
|
||||||
|
assert sgn(NegInf) == -1
|
||||||
|
assert sgn(Inf) == 1
|
||||||
|
assert sgn(NaN) == 0
|
||||||
|
|
||||||
|
block: # fac() tests
|
||||||
|
try:
|
||||||
|
discard fac(-1)
|
||||||
|
except AssertionDefect:
|
||||||
|
discard
|
||||||
|
|
||||||
|
doAssert fac(0) == 1
|
||||||
|
doAssert fac(1) == 1
|
||||||
|
doAssert fac(2) == 2
|
||||||
|
doAssert fac(3) == 6
|
||||||
|
doAssert fac(4) == 24
|
||||||
|
|
||||||
|
block: # floorMod/floorDiv
|
||||||
|
doAssert floorDiv(8, 3) == 2
|
||||||
|
doAssert floorMod(8, 3) == 2
|
||||||
|
|
||||||
|
doAssert floorDiv(8, -3) == -3
|
||||||
|
doAssert floorMod(8, -3) == -1
|
||||||
|
|
||||||
|
doAssert floorDiv(-8, 3) == -3
|
||||||
|
doAssert floorMod(-8, 3) == 1
|
||||||
|
|
||||||
|
doAssert floorDiv(-8, -3) == 2
|
||||||
|
doAssert floorMod(-8, -3) == -2
|
||||||
|
|
||||||
|
doAssert floorMod(8.0, -3.0) ==~ -1.0
|
||||||
|
doAssert floorMod(-8.5, 3.0) ==~ 0.5
|
||||||
|
|
||||||
|
block: # log
|
||||||
|
doAssert log(4.0, 3.0) ==~ ln(4.0) / ln(3.0)
|
||||||
|
doAssert log2(8.0'f64) == 3.0'f64
|
||||||
|
doAssert log2(4.0'f64) == 2.0'f64
|
||||||
|
doAssert log2(2.0'f64) == 1.0'f64
|
||||||
|
doAssert log2(1.0'f64) == 0.0'f64
|
||||||
|
doAssert classify(log2(0.0'f64)) == fcNegInf
|
||||||
|
|
||||||
|
doAssert log2(8.0'f32) == 3.0'f32
|
||||||
|
doAssert log2(4.0'f32) == 2.0'f32
|
||||||
|
doAssert log2(2.0'f32) == 1.0'f32
|
||||||
|
doAssert log2(1.0'f32) == 0.0'f32
|
||||||
|
doAssert classify(log2(0.0'f32)) == fcNegInf
|
||||||
|
|
|
||||||
7
tests/stdlib/tmd5.nim
Normal file
7
tests/stdlib/tmd5.nim
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import md5
|
||||||
|
|
||||||
|
assert(getMD5("Franz jagt im komplett verwahrlosten Taxi quer durch Bayern") ==
|
||||||
|
"a3cca2b2aa1e3b5b3b5aad99a8529074")
|
||||||
|
assert(getMD5("Frank jagt im komplett verwahrlosten Taxi quer durch Bayern") ==
|
||||||
|
"7e716d0e702df0505fc72e2b89467910")
|
||||||
|
assert($toMD5("") == "d41d8cd98f00b204e9800998ecf8427e")
|
||||||
16
tests/stdlib/tmonotimes.nim
Normal file
16
tests/stdlib/tmonotimes.nim
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import std/monotimes, times
|
||||||
|
|
||||||
|
let d = initDuration(nanoseconds = 10)
|
||||||
|
let t1 = getMonoTime()
|
||||||
|
let t2 = t1 + d
|
||||||
|
|
||||||
|
doAssert t2 - t1 == d
|
||||||
|
doAssert t1 == t1
|
||||||
|
doAssert t1 != t2
|
||||||
|
doAssert t2 - d == t1
|
||||||
|
doAssert t1 < t2
|
||||||
|
doAssert t1 <= t2
|
||||||
|
doAssert t1 <= t1
|
||||||
|
doAssert not(t2 < t1)
|
||||||
|
doAssert t1 < high(MonoTime)
|
||||||
|
doAssert low(MonoTime) < t1
|
||||||
|
|
@ -13,4 +13,146 @@ type
|
||||||
let js = """{"foo": {"test": "123"}}"""
|
let js = """{"foo": {"test": "123"}}"""
|
||||||
let parsed = parseJson(js)
|
let parsed = parseJson(js)
|
||||||
let a = parsed.to(Test)
|
let a = parsed.to(Test)
|
||||||
echo $(%*a)
|
echo $(%*a)
|
||||||
|
|
||||||
|
|
||||||
|
# RefPerson is used to test that overloaded `==` operator is not called by
|
||||||
|
# options. It is defined here in the global scope, because otherwise the test
|
||||||
|
# will not even consider the `==` operator. Different bug?
|
||||||
|
type RefPerson = ref object
|
||||||
|
name: string
|
||||||
|
|
||||||
|
proc `==`(a, b: RefPerson): bool =
|
||||||
|
assert(not a.isNil and not b.isNil)
|
||||||
|
a.name == b.name
|
||||||
|
|
||||||
|
block options:
|
||||||
|
# work around a bug in unittest
|
||||||
|
let intNone = none(int)
|
||||||
|
let stringNone = none(string)
|
||||||
|
|
||||||
|
block example:
|
||||||
|
proc find(haystack: string, needle: char): Option[int] =
|
||||||
|
for i, c in haystack:
|
||||||
|
if c == needle:
|
||||||
|
return some i
|
||||||
|
|
||||||
|
doAssert("abc".find('c').get() == 2)
|
||||||
|
|
||||||
|
let result = "team".find('i')
|
||||||
|
|
||||||
|
doAssert result == intNone
|
||||||
|
doAssert result.isNone
|
||||||
|
|
||||||
|
block some:
|
||||||
|
doAssert some(6).get() == 6
|
||||||
|
doAssert some("a").unsafeGet() == "a"
|
||||||
|
doAssert some(6).isSome
|
||||||
|
doAssert some("a").isSome
|
||||||
|
|
||||||
|
block none:
|
||||||
|
doAssertRaises UnpackDefect:
|
||||||
|
discard none(int).get()
|
||||||
|
doAssert(none(int).isNone)
|
||||||
|
doAssert(not none(string).isSome)
|
||||||
|
|
||||||
|
block equality:
|
||||||
|
doAssert some("a") == some("a")
|
||||||
|
doAssert some(7) != some(6)
|
||||||
|
doAssert some("a") != stringNone
|
||||||
|
doAssert intNone == intNone
|
||||||
|
|
||||||
|
when compiles(some("a") == some(5)):
|
||||||
|
doAssert false
|
||||||
|
when compiles(none(string) == none(int)):
|
||||||
|
doAssert false
|
||||||
|
|
||||||
|
block get_with_a_default_value:
|
||||||
|
doAssert(some("Correct").get("Wrong") == "Correct")
|
||||||
|
doAssert(stringNone.get("Correct") == "Correct")
|
||||||
|
|
||||||
|
block stringify:
|
||||||
|
doAssert($(some("Correct")) == "Some(\"Correct\")")
|
||||||
|
doAssert($(stringNone) == "None[string]")
|
||||||
|
|
||||||
|
block map_with_a_void_result:
|
||||||
|
var procRan = 0
|
||||||
|
some(123).map(proc (v: int) = procRan = v)
|
||||||
|
doAssert procRan == 123
|
||||||
|
intNone.map(proc (v: int) = doAssert false)
|
||||||
|
|
||||||
|
block map:
|
||||||
|
doAssert(some(123).map(proc (v: int): int = v * 2) == some(246))
|
||||||
|
doAssert(intNone.map(proc (v: int): int = v * 2).isNone)
|
||||||
|
|
||||||
|
block filter:
|
||||||
|
doAssert(some(123).filter(proc (v: int): bool = v == 123) == some(123))
|
||||||
|
doAssert(some(456).filter(proc (v: int): bool = v == 123).isNone)
|
||||||
|
doAssert(intNone.filter(proc (v: int): bool = doAssert false).isNone)
|
||||||
|
|
||||||
|
block flatMap:
|
||||||
|
proc addOneIfNotZero(v: int): Option[int] =
|
||||||
|
if v != 0:
|
||||||
|
result = some(v + 1)
|
||||||
|
else:
|
||||||
|
result = none(int)
|
||||||
|
|
||||||
|
doAssert(some(1).flatMap(addOneIfNotZero) == some(2))
|
||||||
|
doAssert(some(0).flatMap(addOneIfNotZero) == none(int))
|
||||||
|
doAssert(some(1).flatMap(addOneIfNotZero).flatMap(addOneIfNotZero) == some(3))
|
||||||
|
|
||||||
|
proc maybeToString(v: int): Option[string] =
|
||||||
|
if v != 0:
|
||||||
|
result = some($v)
|
||||||
|
else:
|
||||||
|
result = none(string)
|
||||||
|
|
||||||
|
doAssert(some(1).flatMap(maybeToString) == some("1"))
|
||||||
|
|
||||||
|
proc maybeExclaim(v: string): Option[string] =
|
||||||
|
if v != "":
|
||||||
|
result = some v & "!"
|
||||||
|
else:
|
||||||
|
result = none(string)
|
||||||
|
|
||||||
|
doAssert(some(1).flatMap(maybeToString).flatMap(maybeExclaim) == some("1!"))
|
||||||
|
doAssert(some(0).flatMap(maybeToString).flatMap(maybeExclaim) == none(string))
|
||||||
|
|
||||||
|
block SomePointer:
|
||||||
|
var intref: ref int
|
||||||
|
doAssert(option(intref).isNone)
|
||||||
|
intref.new
|
||||||
|
doAssert(option(intref).isSome)
|
||||||
|
|
||||||
|
let tmp = option(intref)
|
||||||
|
doAssert(sizeof(tmp) == sizeof(ptr int))
|
||||||
|
|
||||||
|
var prc = proc (x: int): int = x + 1
|
||||||
|
doAssert(option(prc).isSome)
|
||||||
|
prc = nil
|
||||||
|
doAssert(option(prc).isNone)
|
||||||
|
|
||||||
|
block:
|
||||||
|
doAssert(none[int]().isNone)
|
||||||
|
doAssert(none(int) == none[int]())
|
||||||
|
|
||||||
|
# "$ on typed with .name"
|
||||||
|
block:
|
||||||
|
type Named = object
|
||||||
|
name: string
|
||||||
|
|
||||||
|
let nobody = none(Named)
|
||||||
|
doAssert($nobody == "None[Named]")
|
||||||
|
|
||||||
|
# "$ on type with name()"
|
||||||
|
block:
|
||||||
|
type Person = object
|
||||||
|
myname: string
|
||||||
|
|
||||||
|
let noperson = none(Person)
|
||||||
|
doAssert($noperson == "None[Person]")
|
||||||
|
|
||||||
|
# "Ref type with overloaded `==`"
|
||||||
|
block:
|
||||||
|
let p = some(RefPerson.new())
|
||||||
|
doAssert p.isSome
|
||||||
|
|
|
||||||
31
tests/stdlib/tparsecsv.nim
Normal file
31
tests/stdlib/tparsecsv.nim
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
include parsecsv
|
||||||
|
import strutils, os
|
||||||
|
|
||||||
|
block: # Tests for reading the header row
|
||||||
|
let content = "\nOne,Two,Three,Four\n1,2,3,4\n10,20,30,40,\n100,200,300,400\n"
|
||||||
|
writeFile("temp.csv", content)
|
||||||
|
|
||||||
|
var p: CsvParser
|
||||||
|
p.open("temp.csv")
|
||||||
|
p.readHeaderRow()
|
||||||
|
while p.readRow():
|
||||||
|
let zeros = repeat('0', p.currRow-2)
|
||||||
|
doAssert p.rowEntry("One") == "1" & zeros
|
||||||
|
doAssert p.rowEntry("Two") == "2" & zeros
|
||||||
|
doAssert p.rowEntry("Three") == "3" & zeros
|
||||||
|
doAssert p.rowEntry("Four") == "4" & zeros
|
||||||
|
p.close()
|
||||||
|
|
||||||
|
when not defined(testing):
|
||||||
|
var parser: CsvParser
|
||||||
|
parser.open("temp.csv")
|
||||||
|
parser.readHeaderRow()
|
||||||
|
while parser.readRow():
|
||||||
|
echo "new row: "
|
||||||
|
for col in items(parser.headers):
|
||||||
|
echo "##", col, ":", parser.rowEntry(col), "##"
|
||||||
|
parser.close()
|
||||||
|
removeFile("temp.csv")
|
||||||
|
|
||||||
|
# Tidy up
|
||||||
|
removeFile("temp.csv")
|
||||||
43
tests/stdlib/tparseutils.nim
Normal file
43
tests/stdlib/tparseutils.nim
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
import parseutils
|
||||||
|
import sequtils
|
||||||
|
|
||||||
|
let input = "$test{} $this is ${an{ example}} "
|
||||||
|
let expected = @[(ikVar, "test"), (ikStr, "{} "), (ikVar, "this"),
|
||||||
|
(ikStr, " is "), (ikExpr, "an{ example}"), (ikStr, " ")]
|
||||||
|
doAssert toSeq(interpolatedFragments(input)) == expected
|
||||||
|
|
||||||
|
var value = 0
|
||||||
|
discard parseHex("0x38", value)
|
||||||
|
doAssert value == 56
|
||||||
|
|
||||||
|
value = -1
|
||||||
|
doAssert(parseSaturatedNatural("848", value) == 3)
|
||||||
|
doAssert value == 848
|
||||||
|
|
||||||
|
value = -1
|
||||||
|
discard parseSaturatedNatural("84899999999999999999324234243143142342135435342532453", value)
|
||||||
|
doAssert value == high(int)
|
||||||
|
|
||||||
|
value = -1
|
||||||
|
discard parseSaturatedNatural("9223372036854775808", value)
|
||||||
|
doAssert value == high(int)
|
||||||
|
|
||||||
|
value = -1
|
||||||
|
discard parseSaturatedNatural("9223372036854775807", value)
|
||||||
|
doAssert value == high(int)
|
||||||
|
|
||||||
|
value = -1
|
||||||
|
discard parseSaturatedNatural("18446744073709551616", value)
|
||||||
|
doAssert value == high(int)
|
||||||
|
|
||||||
|
value = -1
|
||||||
|
discard parseSaturatedNatural("18446744073709551615", value)
|
||||||
|
doAssert value == high(int)
|
||||||
|
|
||||||
|
value = -1
|
||||||
|
doAssert(parseSaturatedNatural("1_000_000", value) == 9)
|
||||||
|
doAssert value == 1_000_000
|
||||||
|
|
||||||
|
var i64Value: int64
|
||||||
|
discard parseBiggestInt("9223372036854775807", i64Value)
|
||||||
|
doAssert i64Value == 9223372036854775807
|
||||||
5
tests/stdlib/tpunycode.nim
Normal file
5
tests/stdlib/tpunycode.nim
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
import punycode
|
||||||
|
|
||||||
|
assert(decode(encode("", "bücher")) == "bücher")
|
||||||
|
assert(decode(encode("münchen")) == "münchen")
|
||||||
|
assert encode("xn--", "münchen") == "xn--mnchen-3ya"
|
||||||
59
tests/stdlib/trandom.nim
Normal file
59
tests/stdlib/trandom.nim
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
discard """
|
||||||
|
action: compile
|
||||||
|
"""
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
proc main =
|
||||||
|
var occur: array[1000, int]
|
||||||
|
|
||||||
|
var x = 8234
|
||||||
|
for i in 0..100_000:
|
||||||
|
x = rand(high(occur))
|
||||||
|
inc occur[x]
|
||||||
|
for i, oc in occur:
|
||||||
|
if oc < 69:
|
||||||
|
doAssert false, "too few occurrences of " & $i
|
||||||
|
elif oc > 150:
|
||||||
|
doAssert false, "too many occurrences of " & $i
|
||||||
|
|
||||||
|
when false:
|
||||||
|
var rs: RunningStat
|
||||||
|
for j in 1..5:
|
||||||
|
for i in 1 .. 1_000:
|
||||||
|
rs.push(gauss())
|
||||||
|
echo("mean: ", rs.mean,
|
||||||
|
" stdDev: ", rs.standardDeviation(),
|
||||||
|
" min: ", rs.min,
|
||||||
|
" max: ", rs.max)
|
||||||
|
rs.clear()
|
||||||
|
|
||||||
|
var a = [0, 1]
|
||||||
|
shuffle(a)
|
||||||
|
doAssert a[0] == 1
|
||||||
|
doAssert a[1] == 0
|
||||||
|
|
||||||
|
doAssert rand(0) == 0
|
||||||
|
doAssert sample("a") == 'a'
|
||||||
|
|
||||||
|
when compileOption("rangeChecks"):
|
||||||
|
try:
|
||||||
|
discard rand(-1)
|
||||||
|
doAssert false
|
||||||
|
except RangeDefect:
|
||||||
|
discard
|
||||||
|
|
||||||
|
try:
|
||||||
|
discard rand(-1.0)
|
||||||
|
doAssert false
|
||||||
|
except RangeDefect:
|
||||||
|
discard
|
||||||
|
|
||||||
|
|
||||||
|
# don't use causes integer overflow
|
||||||
|
doAssert compiles(rand[int](low(int) .. high(int)))
|
||||||
|
|
||||||
|
randomize(223)
|
||||||
|
|
||||||
|
for i in 0 .. 10:
|
||||||
|
main()
|
||||||
98
tests/stdlib/trationals.nim
Normal file
98
tests/stdlib/trationals.nim
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
import rationals, math
|
||||||
|
|
||||||
|
|
||||||
|
var
|
||||||
|
z = Rational[int](num: 0, den: 1)
|
||||||
|
o = initRational(num = 1, den = 1)
|
||||||
|
a = initRational(1, 2)
|
||||||
|
b = -1 // -2
|
||||||
|
m1 = -1 // 1
|
||||||
|
tt = 10 // 2
|
||||||
|
|
||||||
|
assert(a == a)
|
||||||
|
assert( (a-a) == z)
|
||||||
|
assert( (a+b) == o)
|
||||||
|
assert( (a/b) == o)
|
||||||
|
assert( (a*b) == 1 // 4)
|
||||||
|
assert( (3/a) == 6 // 1)
|
||||||
|
assert( (a/3) == 1 // 6)
|
||||||
|
assert(a*b == 1 // 4)
|
||||||
|
assert(tt*z == z)
|
||||||
|
assert(10*a == tt)
|
||||||
|
assert(a*10 == tt)
|
||||||
|
assert(tt/10 == a)
|
||||||
|
assert(a-m1 == 3 // 2)
|
||||||
|
assert(a+m1 == -1 // 2)
|
||||||
|
assert(m1+tt == 16 // 4)
|
||||||
|
assert(m1-tt == 6 // -1)
|
||||||
|
|
||||||
|
assert(z < o)
|
||||||
|
assert(z <= o)
|
||||||
|
assert(z == z)
|
||||||
|
assert(cmp(z, o) < 0)
|
||||||
|
assert(cmp(o, z) > 0)
|
||||||
|
|
||||||
|
assert(o == o)
|
||||||
|
assert(o >= o)
|
||||||
|
assert(not(o > o))
|
||||||
|
assert(cmp(o, o) == 0)
|
||||||
|
assert(cmp(z, z) == 0)
|
||||||
|
assert(hash(o) == hash(o))
|
||||||
|
|
||||||
|
assert(a == b)
|
||||||
|
assert(a >= b)
|
||||||
|
assert(not(b > a))
|
||||||
|
assert(cmp(a, b) == 0)
|
||||||
|
assert(hash(a) == hash(b))
|
||||||
|
|
||||||
|
var x = 1//3
|
||||||
|
|
||||||
|
x *= 5//1
|
||||||
|
assert(x == 5//3)
|
||||||
|
x += 2 // 9
|
||||||
|
assert(x == 17//9)
|
||||||
|
x -= 9//18
|
||||||
|
assert(x == 25//18)
|
||||||
|
x /= 1//2
|
||||||
|
assert(x == 50//18)
|
||||||
|
|
||||||
|
var y = 1//3
|
||||||
|
|
||||||
|
y *= 4
|
||||||
|
assert(y == 4//3)
|
||||||
|
y += 5
|
||||||
|
assert(y == 19//3)
|
||||||
|
y -= 2
|
||||||
|
assert(y == 13//3)
|
||||||
|
y /= 9
|
||||||
|
assert(y == 13//27)
|
||||||
|
|
||||||
|
assert toRational(5) == 5//1
|
||||||
|
assert abs(toFloat(y) - 0.4814814814814815) < 1.0e-7
|
||||||
|
assert toInt(z) == 0
|
||||||
|
|
||||||
|
when sizeof(int) == 8:
|
||||||
|
assert toRational(0.98765432) == 2111111029 // 2137499919
|
||||||
|
assert toRational(PI) == 817696623 // 260280919
|
||||||
|
when sizeof(int) == 4:
|
||||||
|
assert toRational(0.98765432) == 80 // 81
|
||||||
|
assert toRational(PI) == 355 // 113
|
||||||
|
|
||||||
|
assert toRational(0.1) == 1 // 10
|
||||||
|
assert toRational(0.9) == 9 // 10
|
||||||
|
|
||||||
|
assert toRational(0.0) == 0 // 1
|
||||||
|
assert toRational(-0.25) == 1 // -4
|
||||||
|
assert toRational(3.2) == 16 // 5
|
||||||
|
assert toRational(0.33) == 33 // 100
|
||||||
|
assert toRational(0.22) == 11 // 50
|
||||||
|
assert toRational(10.0) == 10 // 1
|
||||||
|
|
||||||
|
assert (1//1) div (3//10) == 3
|
||||||
|
assert (-1//1) div (3//10) == -3
|
||||||
|
assert (3//10) mod (1//1) == 3//10
|
||||||
|
assert (-3//10) mod (1//1) == -3//10
|
||||||
|
assert floorDiv(1//1, 3//10) == 3
|
||||||
|
assert floorDiv(-1//1, 3//10) == -4
|
||||||
|
assert floorMod(3//10, 1//1) == 3//10
|
||||||
|
assert floorMod(-3//10, 1//1) == 7//10
|
||||||
13
tests/stdlib/tsha1.nim
Normal file
13
tests/stdlib/tsha1.nim
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import std/sha1
|
||||||
|
|
||||||
|
let hash1 = secureHash("a93tgj0p34jagp9[agjp98ajrhp9aej]")
|
||||||
|
doAssert hash1 == hash1
|
||||||
|
doAssert parseSecureHash($hash1) == hash1
|
||||||
|
|
||||||
|
template checkVector(s, exp: string) =
|
||||||
|
doAssert secureHash(s) == parseSecureHash(exp)
|
||||||
|
|
||||||
|
checkVector("", "da39a3ee5e6b4b0d3255bfef95601890afd80709")
|
||||||
|
checkVector("abc", "a9993e364706816aba3e25717850c26c9cd0d89d")
|
||||||
|
checkVector("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||||
|
"84983e441c3bd26ebaae4aa1f95129e5e54670f1")
|
||||||
46
tests/stdlib/tstats.nim
Normal file
46
tests/stdlib/tstats.nim
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
include stats
|
||||||
|
|
||||||
|
proc clean(x: float): float =
|
||||||
|
result = round(1.0e8*x).float * 1.0e-8
|
||||||
|
|
||||||
|
var rs: RunningStat
|
||||||
|
rs.push(@[1.0, 2.0, 1.0, 4.0, 1.0, 4.0, 1.0, 2.0])
|
||||||
|
doAssert(rs.n == 8)
|
||||||
|
doAssert(clean(rs.mean) == 2.0)
|
||||||
|
doAssert(clean(rs.variance()) == 1.5)
|
||||||
|
doAssert(clean(rs.varianceS()) == 1.71428571)
|
||||||
|
doAssert(clean(rs.skewness()) == 0.81649658)
|
||||||
|
doAssert(clean(rs.skewnessS()) == 1.01835015)
|
||||||
|
doAssert(clean(rs.kurtosis()) == -1.0)
|
||||||
|
doAssert(clean(rs.kurtosisS()) == -0.7000000000000001)
|
||||||
|
|
||||||
|
var rs1, rs2: RunningStat
|
||||||
|
rs1.push(@[1.0, 2.0, 1.0, 4.0])
|
||||||
|
rs2.push(@[1.0, 4.0, 1.0, 2.0])
|
||||||
|
let rs3 = rs1 + rs2
|
||||||
|
doAssert(clean(rs3.mom2) == clean(rs.mom2))
|
||||||
|
doAssert(clean(rs3.mom3) == clean(rs.mom3))
|
||||||
|
doAssert(clean(rs3.mom4) == clean(rs.mom4))
|
||||||
|
rs1 += rs2
|
||||||
|
doAssert(clean(rs1.mom2) == clean(rs.mom2))
|
||||||
|
doAssert(clean(rs1.mom3) == clean(rs.mom3))
|
||||||
|
doAssert(clean(rs1.mom4) == clean(rs.mom4))
|
||||||
|
rs1.clear()
|
||||||
|
rs1.push(@[1.0, 2.2, 1.4, 4.9])
|
||||||
|
doAssert(rs1.sum == 9.5)
|
||||||
|
doAssert(rs1.mean() == 2.375)
|
||||||
|
|
||||||
|
when not defined(cpu32):
|
||||||
|
# XXX For some reason on 32bit CPUs these results differ
|
||||||
|
var rr: RunningRegress
|
||||||
|
rr.push(@[0.0, 1.0, 2.8, 3.0, 4.0], @[0.0, 1.0, 2.3, 3.0, 4.0])
|
||||||
|
doAssert(rr.slope() == 0.9695585996955861)
|
||||||
|
doAssert(rr.intercept() == -0.03424657534246611)
|
||||||
|
doAssert(rr.correlation() == 0.9905100362239381)
|
||||||
|
var rr1, rr2: RunningRegress
|
||||||
|
rr1.push(@[0.0, 1.0], @[0.0, 1.0])
|
||||||
|
rr2.push(@[2.8, 3.0, 4.0], @[2.3, 3.0, 4.0])
|
||||||
|
let rr3 = rr1 + rr2
|
||||||
|
doAssert(rr3.correlation() == rr.correlation())
|
||||||
|
doAssert(clean(rr3.slope()) == clean(rr.slope()))
|
||||||
|
doAssert(clean(rr3.intercept()) == clean(rr.intercept()))
|
||||||
|
|
@ -61,3 +61,17 @@ doAssert a.readDataStr(buffer, 1..3) == 3
|
||||||
|
|
||||||
echo buffer
|
echo buffer
|
||||||
|
|
||||||
|
|
||||||
|
block:
|
||||||
|
var ss = newStringStream("The quick brown fox jumped over the lazy dog.\nThe lazy dog ran")
|
||||||
|
assert(ss.getPosition == 0)
|
||||||
|
assert(ss.peekStr(5) == "The q")
|
||||||
|
assert(ss.getPosition == 0) # haven't moved
|
||||||
|
assert(ss.readStr(5) == "The q")
|
||||||
|
assert(ss.getPosition == 5) # did move
|
||||||
|
assert(ss.peekLine() == "uick brown fox jumped over the lazy dog.")
|
||||||
|
assert(ss.getPosition == 5) # haven't moved
|
||||||
|
var str = newString(100)
|
||||||
|
assert(ss.peekLine(str))
|
||||||
|
assert(str == "uick brown fox jumped over the lazy dog.")
|
||||||
|
assert(ss.getPosition == 5) # haven't moved
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ output: '''Received (name: "Foo", species: "Bar")'''
|
||||||
# issue #7632
|
# issue #7632
|
||||||
|
|
||||||
import genericstrformat
|
import genericstrformat
|
||||||
import strutils
|
import strutils, times
|
||||||
|
|
||||||
|
|
||||||
doAssert works(5) == "formatted 5"
|
doAssert works(5) == "formatted 5"
|
||||||
|
|
@ -376,3 +376,140 @@ block:
|
||||||
doAssert fmt"{x.foo(y) =}" == "x.foo(y) =18"
|
doAssert fmt"{x.foo(y) =}" == "x.foo(y) =18"
|
||||||
doAssert fmt"{x.foo(y)= }" == "x.foo(y)= 18"
|
doAssert fmt"{x.foo(y)= }" == "x.foo(y)= 18"
|
||||||
doAssert fmt"{x.foo(y) = }" == "x.foo(y) = 18"
|
doAssert fmt"{x.foo(y) = }" == "x.foo(y) = 18"
|
||||||
|
|
||||||
|
block:
|
||||||
|
template check(actual, expected: string) =
|
||||||
|
doAssert actual == expected
|
||||||
|
|
||||||
|
# Basic tests
|
||||||
|
let s = "string"
|
||||||
|
check &"{0} {s}", "0 string"
|
||||||
|
check &"{s[0..2].toUpperAscii}", "STR"
|
||||||
|
check &"{-10:04}", "-010"
|
||||||
|
check &"{-10:<04}", "-010"
|
||||||
|
check &"{-10:>04}", "-010"
|
||||||
|
check &"0x{10:02X}", "0x0A"
|
||||||
|
|
||||||
|
check &"{10:#04X}", "0x0A"
|
||||||
|
|
||||||
|
check &"""{"test":#>5}""", "#test"
|
||||||
|
check &"""{"test":>5}""", " test"
|
||||||
|
|
||||||
|
check &"""{"test":#^7}""", "#test##"
|
||||||
|
|
||||||
|
check &"""{"test": <5}""", "test "
|
||||||
|
check &"""{"test":<5}""", "test "
|
||||||
|
check &"{1f:.3f}", "1.000"
|
||||||
|
check &"Hello, {s}!", "Hello, string!"
|
||||||
|
|
||||||
|
# Tests for identifiers without parenthesis
|
||||||
|
check &"{s} works{s}", "string worksstring"
|
||||||
|
check &"{s:>7}", " string"
|
||||||
|
doAssert(not compiles(&"{s_works}")) # parsed as identifier `s_works`
|
||||||
|
|
||||||
|
# Misc general tests
|
||||||
|
check &"{{}}", "{}"
|
||||||
|
check &"{0}%", "0%"
|
||||||
|
check &"{0}%asdf", "0%asdf"
|
||||||
|
check &("\n{\"\\n\"}\n"), "\n\n\n"
|
||||||
|
check &"""{"abc"}s""", "abcs"
|
||||||
|
|
||||||
|
# String tests
|
||||||
|
check &"""{"abc"}""", "abc"
|
||||||
|
check &"""{"abc":>4}""", " abc"
|
||||||
|
check &"""{"abc":<4}""", "abc "
|
||||||
|
check &"""{"":>4}""", " "
|
||||||
|
check &"""{"":<4}""", " "
|
||||||
|
|
||||||
|
# Int tests
|
||||||
|
check &"{12345}", "12345"
|
||||||
|
check &"{ - 12345}", "-12345"
|
||||||
|
check &"{12345:6}", " 12345"
|
||||||
|
check &"{12345:>6}", " 12345"
|
||||||
|
check &"{12345:4}", "12345"
|
||||||
|
check &"{12345:08}", "00012345"
|
||||||
|
check &"{-12345:08}", "-0012345"
|
||||||
|
check &"{0:0}", "0"
|
||||||
|
check &"{0:02}", "00"
|
||||||
|
check &"{-1:3}", " -1"
|
||||||
|
check &"{-1:03}", "-01"
|
||||||
|
check &"{10}", "10"
|
||||||
|
check &"{16:#X}", "0x10"
|
||||||
|
check &"{16:^#7X}", " 0x10 "
|
||||||
|
check &"{16:^+#7X}", " +0x10 "
|
||||||
|
|
||||||
|
# Hex tests
|
||||||
|
check &"{0:x}", "0"
|
||||||
|
check &"{-0:x}", "0"
|
||||||
|
check &"{255:x}", "ff"
|
||||||
|
check &"{255:X}", "FF"
|
||||||
|
check &"{-255:x}", "-ff"
|
||||||
|
check &"{-255:X}", "-FF"
|
||||||
|
check &"{255:x} uNaffeCteD CaSe", "ff uNaffeCteD CaSe"
|
||||||
|
check &"{255:X} uNaffeCteD CaSe", "FF uNaffeCteD CaSe"
|
||||||
|
check &"{255:4x}", " ff"
|
||||||
|
check &"{255:04x}", "00ff"
|
||||||
|
check &"{-255:4x}", " -ff"
|
||||||
|
check &"{-255:04x}", "-0ff"
|
||||||
|
|
||||||
|
# Float tests
|
||||||
|
check &"{123.456}", "123.456"
|
||||||
|
check &"{-123.456}", "-123.456"
|
||||||
|
check &"{123.456:.3f}", "123.456"
|
||||||
|
check &"{123.456:+.3f}", "+123.456"
|
||||||
|
check &"{-123.456:+.3f}", "-123.456"
|
||||||
|
check &"{-123.456:.3f}", "-123.456"
|
||||||
|
check &"{123.456:1g}", "123.456"
|
||||||
|
check &"{123.456:.1f}", "123.5"
|
||||||
|
check &"{123.456:.0f}", "123."
|
||||||
|
check &"{123.456:>9.3f}", " 123.456"
|
||||||
|
check &"{123.456:9.3f}", " 123.456"
|
||||||
|
check &"{123.456:>9.4f}", " 123.4560"
|
||||||
|
check &"{123.456:>9.0f}", " 123."
|
||||||
|
check &"{123.456:<9.4f}", "123.4560 "
|
||||||
|
|
||||||
|
# Float (scientific) tests
|
||||||
|
check &"{123.456:e}", "1.234560e+02"
|
||||||
|
check &"{123.456:>13e}", " 1.234560e+02"
|
||||||
|
check &"{123.456:<13e}", "1.234560e+02 "
|
||||||
|
check &"{123.456:.1e}", "1.2e+02"
|
||||||
|
check &"{123.456:.2e}", "1.23e+02"
|
||||||
|
check &"{123.456:.3e}", "1.235e+02"
|
||||||
|
|
||||||
|
# Note: times.format adheres to the format protocol. Test that this
|
||||||
|
# works:
|
||||||
|
|
||||||
|
var dt = initDateTime(01, mJan, 2000, 00, 00, 00)
|
||||||
|
check &"{dt:yyyy-MM-dd}", "2000-01-01"
|
||||||
|
|
||||||
|
var tm = fromUnix(0)
|
||||||
|
discard &"{tm}"
|
||||||
|
|
||||||
|
var noww = now()
|
||||||
|
check &"{noww}", $noww
|
||||||
|
|
||||||
|
# Unicode string tests
|
||||||
|
check &"""{"αβγ"}""", "αβγ"
|
||||||
|
check &"""{"αβγ":>5}""", " αβγ"
|
||||||
|
check &"""{"αβγ":<5}""", "αβγ "
|
||||||
|
check &"""a{"a"}α{"α"}€{"€"}𐍈{"𐍈"}""", "aaαα€€𐍈𐍈"
|
||||||
|
check &"""a{"a":2}α{"α":2}€{"€":2}𐍈{"𐍈":2}""", "aa αα €€ 𐍈𐍈 "
|
||||||
|
# Invalid unicode sequences should be handled as plain strings.
|
||||||
|
# Invalid examples taken from: https://stackoverflow.com/a/3886015/1804173
|
||||||
|
let invalidUtf8 = [
|
||||||
|
"\xc3\x28", "\xa0\xa1",
|
||||||
|
"\xe2\x28\xa1", "\xe2\x82\x28",
|
||||||
|
"\xf0\x28\x8c\xbc", "\xf0\x90\x28\xbc", "\xf0\x28\x8c\x28"
|
||||||
|
]
|
||||||
|
for s in invalidUtf8:
|
||||||
|
check &"{s:>5}", repeat(" ", 5-s.len) & s
|
||||||
|
|
||||||
|
# bug #11089
|
||||||
|
let flfoo: float = 1.0
|
||||||
|
check &"{flfoo}", "1.0"
|
||||||
|
|
||||||
|
# bug #11092
|
||||||
|
check &"{high(int64)}", "9223372036854775807"
|
||||||
|
check &"{low(int64)}", "-9223372036854775808"
|
||||||
|
|
||||||
|
doAssert fmt"{'a'} {'b'}" == "a b"
|
||||||
22
tests/stdlib/tstrmiscs.nim
Normal file
22
tests/stdlib/tstrmiscs.nim
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
import strmisc
|
||||||
|
|
||||||
|
|
||||||
|
doAssert expandTabs("\t", 4) == " "
|
||||||
|
doAssert expandTabs("\tfoo\t", 4) == " foo "
|
||||||
|
doAssert expandTabs("\tfoo\tbar", 4) == " foo bar"
|
||||||
|
doAssert expandTabs("\tfoo\tbar\t", 4) == " foo bar "
|
||||||
|
doAssert expandTabs("", 4) == ""
|
||||||
|
doAssert expandTabs("", 0) == ""
|
||||||
|
doAssert expandTabs("\t\t\t", 0) == ""
|
||||||
|
|
||||||
|
doAssert partition("foo:bar", ":") == ("foo", ":", "bar")
|
||||||
|
doAssert partition("foobarbar", "bar") == ("foo", "bar", "bar")
|
||||||
|
doAssert partition("foobarbar", "bank") == ("foobarbar", "", "")
|
||||||
|
doAssert partition("foobarbar", "foo") == ("", "foo", "barbar")
|
||||||
|
doAssert partition("foofoobar", "bar") == ("foofoo", "bar", "")
|
||||||
|
|
||||||
|
doAssert rpartition("foo:bar", ":") == ("foo", ":", "bar")
|
||||||
|
doAssert rpartition("foobarbar", "bar") == ("foobar", "bar", "")
|
||||||
|
doAssert rpartition("foobarbar", "bank") == ("", "", "foobarbar")
|
||||||
|
doAssert rpartition("foobarbar", "foo") == ("", "foo", "barbar")
|
||||||
|
doAssert rpartition("foofoobar", "bar") == ("foofoo", "bar", "")
|
||||||
|
|
@ -98,3 +98,115 @@ block issue15064:
|
||||||
doAssert scanf("<abcd> ", "<$+> $*", nick3, msg3)
|
doAssert scanf("<abcd> ", "<$+> $*", nick3, msg3)
|
||||||
doAssert nick3 == "abcd"
|
doAssert nick3 == "abcd"
|
||||||
doAssert msg3 == ""
|
doAssert msg3 == ""
|
||||||
|
|
||||||
|
|
||||||
|
block:
|
||||||
|
proc twoDigits(input: string; x: var int; start: int): int =
|
||||||
|
if start+1 < input.len and input[start] == '0' and input[start+1] == '0':
|
||||||
|
result = 2
|
||||||
|
x = 13
|
||||||
|
else:
|
||||||
|
result = 0
|
||||||
|
|
||||||
|
proc someSep(input: string; start: int; seps: set[char] = {';', ',', '-', '.'}): int =
|
||||||
|
result = 0
|
||||||
|
while start+result < input.len and input[start+result] in seps: inc result
|
||||||
|
|
||||||
|
proc demangle(s: string; res: var string; start: int): int =
|
||||||
|
while result+start < s.len and s[result+start] in {'_', '@'}: inc result
|
||||||
|
res = ""
|
||||||
|
while result+start < s.len and s[result+start] > ' ' and s[result+start] != '_':
|
||||||
|
res.add s[result+start]
|
||||||
|
inc result
|
||||||
|
while result+start < s.len and s[result+start] > ' ':
|
||||||
|
inc result
|
||||||
|
|
||||||
|
proc parseGDB(resp: string): seq[string] =
|
||||||
|
const
|
||||||
|
digits = {'0'..'9'}
|
||||||
|
hexdigits = digits + {'a'..'f', 'A'..'F'}
|
||||||
|
whites = {' ', '\t', '\C', '\L'}
|
||||||
|
result = @[]
|
||||||
|
var idx = 0
|
||||||
|
while true:
|
||||||
|
var prc = ""
|
||||||
|
var info = ""
|
||||||
|
if scanp(resp, idx, *`whites`, '#', *`digits`, +`whites`, ?("0x", *`hexdigits`, " in "),
|
||||||
|
demangle($input, prc, $index), *`whites`, '(', * ~ ')', ')',
|
||||||
|
*`whites`, "at ", +(~{'\C', '\L'} -> info.add($_))):
|
||||||
|
result.add prc & " " & info
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
var key, val: string
|
||||||
|
var intval: int
|
||||||
|
var floatval: float
|
||||||
|
doAssert scanf("abc:: xyz 89 33.25", "$w$s::$s$w$s$i $f", key, val, intval, floatVal)
|
||||||
|
doAssert key == "abc"
|
||||||
|
doAssert val == "xyz"
|
||||||
|
doAssert intval == 89
|
||||||
|
doAssert floatVal == 33.25
|
||||||
|
|
||||||
|
var binval: int
|
||||||
|
var octval: int
|
||||||
|
var hexval: int
|
||||||
|
doAssert scanf("0b0101 0o1234 0xabcd", "$b$s$o$s$h", binval, octval, hexval)
|
||||||
|
doAssert binval == 0b0101
|
||||||
|
doAssert octval == 0o1234
|
||||||
|
doAssert hexval == 0xabcd
|
||||||
|
|
||||||
|
let xx = scanf("$abc", "$$$i", intval)
|
||||||
|
doAssert xx == false
|
||||||
|
|
||||||
|
|
||||||
|
let xx2 = scanf("$1234", "$$$i", intval)
|
||||||
|
doAssert xx2
|
||||||
|
|
||||||
|
let yy = scanf(";.--Breakpoint00 [output]",
|
||||||
|
"$[someSep]Breakpoint${twoDigits}$[someSep({';','.','-'})] [$+]$.",
|
||||||
|
intVal, key)
|
||||||
|
doAssert yy
|
||||||
|
doAssert key == "output"
|
||||||
|
doAssert intVal == 13
|
||||||
|
|
||||||
|
var ident = ""
|
||||||
|
var idx = 0
|
||||||
|
let zz = scanp("foobar x x x xWZ", idx, +{'a'..'z'} -> add(ident, $_), *(*{
|
||||||
|
' ', '\t'}, "x"), ~'U', "Z")
|
||||||
|
doAssert zz
|
||||||
|
doAssert ident == "foobar"
|
||||||
|
|
||||||
|
const digits = {'0'..'9'}
|
||||||
|
var year = 0
|
||||||
|
var idx2 = 0
|
||||||
|
if scanp("201655-8-9", idx2, `digits`{4, 6} -> (year = year * 10 + ord($_) -
|
||||||
|
ord('0')), "-8", "-9"):
|
||||||
|
doAssert year == 201655
|
||||||
|
|
||||||
|
const gdbOut = """
|
||||||
|
#0 @foo_96013_1208911747@8 (x0=...)
|
||||||
|
at c:/users/anwender/projects/nim/temp.nim:11
|
||||||
|
#1 0x00417754 in tempInit000 () at c:/users/anwender/projects/nim/temp.nim:13
|
||||||
|
#2 0x0041768d in NimMainInner ()
|
||||||
|
at c:/users/anwender/projects/nim/lib/system.nim:2605
|
||||||
|
#3 0x004176b1 in NimMain ()
|
||||||
|
at c:/users/anwender/projects/nim/lib/system.nim:2613
|
||||||
|
#4 0x004176db in main (argc=1, args=0x712cc8, env=0x711ca8)
|
||||||
|
at c:/users/anwender/projects/nim/lib/system.nim:2620"""
|
||||||
|
const result = @["foo c:/users/anwender/projects/nim/temp.nim:11",
|
||||||
|
"tempInit000 c:/users/anwender/projects/nim/temp.nim:13",
|
||||||
|
"NimMainInner c:/users/anwender/projects/nim/lib/system.nim:2605",
|
||||||
|
"NimMain c:/users/anwender/projects/nim/lib/system.nim:2613",
|
||||||
|
"main c:/users/anwender/projects/nim/lib/system.nim:2620"]
|
||||||
|
doAssert parseGDB(gdbOut) == result
|
||||||
|
|
||||||
|
# bug #6487
|
||||||
|
var count = 0
|
||||||
|
|
||||||
|
proc test(): string =
|
||||||
|
inc count
|
||||||
|
result = ",123123"
|
||||||
|
|
||||||
|
var a: int
|
||||||
|
discard scanf(test(), ",$i", a)
|
||||||
|
doAssert count == 1
|
||||||
|
|
|
||||||
|
|
@ -102,3 +102,15 @@ writeLine(stdout, "length of table ", $tab.len)
|
||||||
writeLine(stdout, `%`("$key1 = $key2", tab, {useEnvironment}))
|
writeLine(stdout, `%`("$key1 = $key2", tab, {useEnvironment}))
|
||||||
tab.clear
|
tab.clear
|
||||||
writeLine(stdout, "length of table ", $tab.len)
|
writeLine(stdout, "length of table ", $tab.len)
|
||||||
|
|
||||||
|
block:
|
||||||
|
var x = {"k": "v", "11": "22", "565": "67"}.newStringTable
|
||||||
|
assert x["k"] == "v"
|
||||||
|
assert x["11"] == "22"
|
||||||
|
assert x["565"] == "67"
|
||||||
|
x["11"] = "23"
|
||||||
|
assert x["11"] == "23"
|
||||||
|
|
||||||
|
x.clear(modeCaseInsensitive)
|
||||||
|
x["11"] = "22"
|
||||||
|
assert x["11"] == "22"
|
||||||
|
|
|
||||||
|
|
@ -457,3 +457,220 @@ hey
|
||||||
assert 0 == indentation ""
|
assert 0 == indentation ""
|
||||||
assert 0 == indentation " \n \n"
|
assert 0 == indentation " \n \n"
|
||||||
assert 0 == indentation " "
|
assert 0 == indentation " "
|
||||||
|
|
||||||
|
|
||||||
|
block:
|
||||||
|
proc nonStaticTests =
|
||||||
|
doAssert formatBiggestFloat(1234.567, ffDecimal, -1) == "1234.567000"
|
||||||
|
when not defined(js):
|
||||||
|
doAssert formatBiggestFloat(1234.567, ffDecimal, 0) == "1235." # bugs 8242, 12586
|
||||||
|
doAssert formatBiggestFloat(1234.567, ffDecimal, 1) == "1234.6"
|
||||||
|
doAssert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001"
|
||||||
|
doAssert formatBiggestFloat(0.00000000001, ffScientific, 1, ',') in
|
||||||
|
["1,0e-11", "1,0e-011"]
|
||||||
|
# bug #6589
|
||||||
|
when not defined(js):
|
||||||
|
doAssert formatFloat(123.456, ffScientific, precision = -1) == "1.234560e+02"
|
||||||
|
|
||||||
|
doAssert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c"
|
||||||
|
doAssert "${1}12 ${-1}$2" % ["a", "b"] == "a12 bb"
|
||||||
|
|
||||||
|
block: # formatSize tests
|
||||||
|
when not defined(js):
|
||||||
|
doAssert formatSize((1'i64 shl 31) + (300'i64 shl 20)) == "2.293GiB" # <=== bug #8231
|
||||||
|
doAssert formatSize((2.234*1024*1024).int) == "2.234MiB"
|
||||||
|
doAssert formatSize(4096) == "4KiB"
|
||||||
|
doAssert formatSize(4096, prefix = bpColloquial, includeSpace = true) == "4 kB"
|
||||||
|
doAssert formatSize(4096, includeSpace = true) == "4 KiB"
|
||||||
|
doAssert formatSize(5_378_934, prefix = bpColloquial, decimalSep = ',') == "5,13MB"
|
||||||
|
|
||||||
|
block: # formatEng tests
|
||||||
|
doAssert formatEng(0, 2, trim = false) == "0.00"
|
||||||
|
doAssert formatEng(0, 2) == "0"
|
||||||
|
doAssert formatEng(53, 2, trim = false) == "53.00"
|
||||||
|
doAssert formatEng(0.053, 2, trim = false) == "53.00e-3"
|
||||||
|
doAssert formatEng(0.053, 4, trim = false) == "53.0000e-3"
|
||||||
|
doAssert formatEng(0.053, 4, trim = true) == "53e-3"
|
||||||
|
doAssert formatEng(0.053, 0) == "53e-3"
|
||||||
|
doAssert formatEng(52731234) == "52.731234e6"
|
||||||
|
doAssert formatEng(-52731234) == "-52.731234e6"
|
||||||
|
doAssert formatEng(52731234, 1) == "52.7e6"
|
||||||
|
doAssert formatEng(-52731234, 1) == "-52.7e6"
|
||||||
|
doAssert formatEng(52731234, 1, decimalSep = ',') == "52,7e6"
|
||||||
|
doAssert formatEng(-52731234, 1, decimalSep = ',') == "-52,7e6"
|
||||||
|
|
||||||
|
doAssert formatEng(4100, siPrefix = true, unit = "V") == "4.1 kV"
|
||||||
|
doAssert formatEng(4.1, siPrefix = true, unit = "V",
|
||||||
|
useUnitSpace = true) == "4.1 V"
|
||||||
|
doAssert formatEng(4.1, siPrefix = true) == "4.1" # Note lack of space
|
||||||
|
doAssert formatEng(4100, siPrefix = true) == "4.1 k"
|
||||||
|
doAssert formatEng(4.1, siPrefix = true, unit = "",
|
||||||
|
useUnitSpace = true) == "4.1 " # Includes space
|
||||||
|
doAssert formatEng(4100, siPrefix = true, unit = "") == "4.1 k"
|
||||||
|
doAssert formatEng(4100) == "4.1e3"
|
||||||
|
doAssert formatEng(4100, unit = "V", useUnitSpace = true) == "4.1e3 V"
|
||||||
|
doAssert formatEng(4100, unit = "", useUnitSpace = true) == "4.1e3 "
|
||||||
|
# Don't use SI prefix as number is too big
|
||||||
|
doAssert formatEng(3.1e22, siPrefix = true, unit = "a",
|
||||||
|
useUnitSpace = true) == "31e21 a"
|
||||||
|
# Don't use SI prefix as number is too small
|
||||||
|
doAssert formatEng(3.1e-25, siPrefix = true, unit = "A",
|
||||||
|
useUnitSpace = true) == "310e-27 A"
|
||||||
|
|
||||||
|
proc staticTests =
|
||||||
|
doAssert align("abc", 4) == " abc"
|
||||||
|
doAssert align("a", 0) == "a"
|
||||||
|
doAssert align("1232", 6) == " 1232"
|
||||||
|
doAssert align("1232", 6, '#') == "##1232"
|
||||||
|
|
||||||
|
doAssert alignLeft("abc", 4) == "abc "
|
||||||
|
doAssert alignLeft("a", 0) == "a"
|
||||||
|
doAssert alignLeft("1232", 6) == "1232 "
|
||||||
|
doAssert alignLeft("1232", 6, '#') == "1232##"
|
||||||
|
|
||||||
|
doAssert "$animal eats $food." % ["animal", "The cat", "food", "fish"] ==
|
||||||
|
"The cat eats fish."
|
||||||
|
|
||||||
|
doAssert "-ld a-ldz -ld".replaceWord("-ld") == " a-ldz "
|
||||||
|
doAssert "-lda-ldz -ld abc".replaceWord("-ld") == "-lda-ldz abc"
|
||||||
|
|
||||||
|
doAssert "-lda-ldz -ld abc".replaceWord("") == "-lda-ldz -ld abc"
|
||||||
|
doAssert "oo".replace("", "abc") == "oo"
|
||||||
|
|
||||||
|
type MyEnum = enum enA, enB, enC, enuD, enE
|
||||||
|
doAssert parseEnum[MyEnum]("enu_D") == enuD
|
||||||
|
|
||||||
|
doAssert parseEnum("invalid enum value", enC) == enC
|
||||||
|
|
||||||
|
doAssert center("foo", 13) == " foo "
|
||||||
|
doAssert center("foo", 0) == "foo"
|
||||||
|
doAssert center("foo", 3, fillChar = 'a') == "foo"
|
||||||
|
doAssert center("foo", 10, fillChar = '\t') == "\t\t\tfoo\t\t\t\t"
|
||||||
|
|
||||||
|
doAssert count("foofoofoo", "foofoo") == 1
|
||||||
|
doAssert count("foofoofoo", "foofoo", overlapping = true) == 2
|
||||||
|
doAssert count("foofoofoo", 'f') == 3
|
||||||
|
doAssert count("foofoofoobar", {'f', 'b'}) == 4
|
||||||
|
|
||||||
|
doAssert strip(" foofoofoo ") == "foofoofoo"
|
||||||
|
doAssert strip("sfoofoofoos", chars = {'s'}) == "foofoofoo"
|
||||||
|
doAssert strip("barfoofoofoobar", chars = {'b', 'a', 'r'}) == "foofoofoo"
|
||||||
|
doAssert strip("stripme but don't strip this stripme",
|
||||||
|
chars = {'s', 't', 'r', 'i', 'p', 'm', 'e'}) ==
|
||||||
|
" but don't strip this "
|
||||||
|
doAssert strip("sfoofoofoos", leading = false, chars = {'s'}) == "sfoofoofoo"
|
||||||
|
doAssert strip("sfoofoofoos", trailing = false, chars = {'s'}) == "foofoofoos"
|
||||||
|
|
||||||
|
doAssert " foo\n bar".indent(4, "Q") == "QQQQ foo\nQQQQ bar"
|
||||||
|
|
||||||
|
doAssert "abba".multiReplace(("a", "b"), ("b", "a")) == "baab"
|
||||||
|
doAssert "Hello World.".multiReplace(("ello", "ELLO"), ("World.",
|
||||||
|
"PEOPLE!")) == "HELLO PEOPLE!"
|
||||||
|
doAssert "aaaa".multiReplace(("a", "aa"), ("aa", "bb")) == "aaaaaaaa"
|
||||||
|
|
||||||
|
doAssert isAlphaAscii('r')
|
||||||
|
doAssert isAlphaAscii('A')
|
||||||
|
doAssert(not isAlphaAscii('$'))
|
||||||
|
|
||||||
|
doAssert isAlphaNumeric('3')
|
||||||
|
doAssert isAlphaNumeric('R')
|
||||||
|
doAssert(not isAlphaNumeric('!'))
|
||||||
|
|
||||||
|
doAssert isDigit('3')
|
||||||
|
doAssert(not isDigit('a'))
|
||||||
|
doAssert(not isDigit('%'))
|
||||||
|
|
||||||
|
doAssert isSpaceAscii('\t')
|
||||||
|
doAssert isSpaceAscii('\l')
|
||||||
|
doAssert(not isSpaceAscii('A'))
|
||||||
|
|
||||||
|
doAssert(isEmptyOrWhitespace(""))
|
||||||
|
doAssert(isEmptyOrWhitespace(" "))
|
||||||
|
doAssert(isEmptyOrWhitespace("\t\l \v\r\f"))
|
||||||
|
doAssert(not isEmptyOrWhitespace("ABc \td"))
|
||||||
|
|
||||||
|
doAssert isLowerAscii('a')
|
||||||
|
doAssert isLowerAscii('z')
|
||||||
|
doAssert(not isLowerAscii('A'))
|
||||||
|
doAssert(not isLowerAscii('5'))
|
||||||
|
doAssert(not isLowerAscii('&'))
|
||||||
|
doAssert(not isLowerAscii(' '))
|
||||||
|
|
||||||
|
doAssert isUpperAscii('A')
|
||||||
|
doAssert(not isUpperAscii('b'))
|
||||||
|
doAssert(not isUpperAscii('5'))
|
||||||
|
doAssert(not isUpperAscii('%'))
|
||||||
|
|
||||||
|
doAssert rsplit("foo bar", seps = Whitespace) == @["foo", "bar"]
|
||||||
|
doAssert rsplit(" foo bar", seps = Whitespace, maxsplit = 1) == @[" foo", "bar"]
|
||||||
|
doAssert rsplit(" foo bar ", seps = Whitespace, maxsplit = 1) == @[
|
||||||
|
" foo bar", ""]
|
||||||
|
doAssert rsplit(":foo:bar", sep = ':') == @["", "foo", "bar"]
|
||||||
|
doAssert rsplit(":foo:bar", sep = ':', maxsplit = 2) == @["", "foo", "bar"]
|
||||||
|
doAssert rsplit(":foo:bar", sep = ':', maxsplit = 3) == @["", "foo", "bar"]
|
||||||
|
doAssert rsplit("foothebar", sep = "the") == @["foo", "bar"]
|
||||||
|
|
||||||
|
doAssert(unescape(r"\x013", "", "") == "\x013")
|
||||||
|
|
||||||
|
doAssert join(["foo", "bar", "baz"]) == "foobarbaz"
|
||||||
|
doAssert join(@["foo", "bar", "baz"], ", ") == "foo, bar, baz"
|
||||||
|
doAssert join([1, 2, 3]) == "123"
|
||||||
|
doAssert join(@[1, 2, 3], ", ") == "1, 2, 3"
|
||||||
|
|
||||||
|
doAssert """~~!!foo
|
||||||
|
~~!!bar
|
||||||
|
~~!!baz""".unindent(2, "~~!!") == "foo\nbar\nbaz"
|
||||||
|
|
||||||
|
doAssert """~~!!foo
|
||||||
|
~~!!bar
|
||||||
|
~~!!baz""".unindent(2, "~~!!aa") == "~~!!foo\n~~!!bar\n~~!!baz"
|
||||||
|
doAssert """~~foo
|
||||||
|
~~ bar
|
||||||
|
~~ baz""".unindent(4, "~") == "foo\n bar\n baz"
|
||||||
|
doAssert """foo
|
||||||
|
bar
|
||||||
|
baz
|
||||||
|
""".unindent(4) == "foo\nbar\nbaz\n"
|
||||||
|
doAssert """foo
|
||||||
|
bar
|
||||||
|
baz
|
||||||
|
""".unindent(2) == "foo\n bar\n baz\n"
|
||||||
|
doAssert """foo
|
||||||
|
bar
|
||||||
|
baz
|
||||||
|
""".unindent(100) == "foo\nbar\nbaz\n"
|
||||||
|
|
||||||
|
doAssert """foo
|
||||||
|
foo
|
||||||
|
bar
|
||||||
|
""".unindent() == "foo\nfoo\nbar\n"
|
||||||
|
|
||||||
|
let s = " this is an example "
|
||||||
|
let s2 = ":this;is;an:example;;"
|
||||||
|
|
||||||
|
doAssert s.split() == @["", "this", "is", "an", "example", "", ""]
|
||||||
|
doAssert s2.split(seps = {':', ';'}) == @["", "this", "is", "an", "example",
|
||||||
|
"", ""]
|
||||||
|
doAssert s.split(maxsplit = 4) == @["", "this", "is", "an", "example "]
|
||||||
|
doAssert s.split(' ', maxsplit = 1) == @["", "this is an example "]
|
||||||
|
doAssert s.split(" ", maxsplit = 4) == @["", "this", "is", "an", "example "]
|
||||||
|
|
||||||
|
doAssert s.splitWhitespace() == @["this", "is", "an", "example"]
|
||||||
|
doAssert s.splitWhitespace(maxsplit = 1) == @["this", "is an example "]
|
||||||
|
doAssert s.splitWhitespace(maxsplit = 2) == @["this", "is", "an example "]
|
||||||
|
doAssert s.splitWhitespace(maxsplit = 3) == @["this", "is", "an", "example "]
|
||||||
|
doAssert s.splitWhitespace(maxsplit = 4) == @["this", "is", "an", "example"]
|
||||||
|
|
||||||
|
block: # startsWith / endsWith char tests
|
||||||
|
var s = "abcdef"
|
||||||
|
doAssert s.startsWith('a')
|
||||||
|
doAssert s.startsWith('b') == false
|
||||||
|
doAssert s.endsWith('f')
|
||||||
|
doAssert s.endsWith('a') == false
|
||||||
|
doAssert s.endsWith('\0') == false
|
||||||
|
|
||||||
|
#echo("strutils tests passed")
|
||||||
|
|
||||||
|
nonStaticTests()
|
||||||
|
staticTests()
|
||||||
|
static: staticTests()
|
||||||
311
tests/stdlib/ttables.nim
Normal file
311
tests/stdlib/ttables.nim
Normal file
|
|
@ -0,0 +1,311 @@
|
||||||
|
import tables, hashes
|
||||||
|
|
||||||
|
type
|
||||||
|
Person = object
|
||||||
|
firstName, lastName: string
|
||||||
|
|
||||||
|
proc hash(x: Person): Hash =
|
||||||
|
## Piggyback on the already available string hash proc.
|
||||||
|
##
|
||||||
|
## Without this proc nothing works!
|
||||||
|
result = x.firstName.hash !& x.lastName.hash
|
||||||
|
result = !$result
|
||||||
|
|
||||||
|
var
|
||||||
|
salaries = initTable[Person, int]()
|
||||||
|
p1, p2: Person
|
||||||
|
p1.firstName = "Jon"
|
||||||
|
p1.lastName = "Ross"
|
||||||
|
salaries[p1] = 30_000
|
||||||
|
p2.firstName = "소진"
|
||||||
|
p2.lastName = "박"
|
||||||
|
salaries[p2] = 45_000
|
||||||
|
var
|
||||||
|
s2 = initOrderedTable[Person, int]()
|
||||||
|
s3 = initCountTable[Person]()
|
||||||
|
s2[p1] = 30_000
|
||||||
|
s2[p2] = 45_000
|
||||||
|
s3[p1] = 30_000
|
||||||
|
s3[p2] = 45_000
|
||||||
|
|
||||||
|
block: # Ordered table should preserve order after deletion
|
||||||
|
var
|
||||||
|
s4 = initOrderedTable[int, int]()
|
||||||
|
s4[1] = 1
|
||||||
|
s4[2] = 2
|
||||||
|
s4[3] = 3
|
||||||
|
|
||||||
|
var prev = 0
|
||||||
|
for i in s4.values:
|
||||||
|
doAssert(prev < i)
|
||||||
|
prev = i
|
||||||
|
|
||||||
|
s4.del(2)
|
||||||
|
doAssert(2 notin s4)
|
||||||
|
doAssert(s4.len == 2)
|
||||||
|
prev = 0
|
||||||
|
for i in s4.values:
|
||||||
|
doAssert(prev < i)
|
||||||
|
prev = i
|
||||||
|
|
||||||
|
block: # Deletion from OrderedTable should account for collision groups. See issue #5057.
|
||||||
|
# The bug is reproducible only with exact keys
|
||||||
|
const key1 = "boy_jackpot.inGamma"
|
||||||
|
const key2 = "boy_jackpot.outBlack"
|
||||||
|
|
||||||
|
var t = {
|
||||||
|
key1: 0,
|
||||||
|
key2: 0
|
||||||
|
}.toOrderedTable()
|
||||||
|
|
||||||
|
t.del(key1)
|
||||||
|
assert(t.len == 1)
|
||||||
|
assert(key2 in t)
|
||||||
|
|
||||||
|
var
|
||||||
|
t1 = initCountTable[string]()
|
||||||
|
t2 = initCountTable[string]()
|
||||||
|
t1.inc("foo")
|
||||||
|
t1.inc("bar", 2)
|
||||||
|
t1.inc("baz", 3)
|
||||||
|
t2.inc("foo", 4)
|
||||||
|
t2.inc("bar")
|
||||||
|
t2.inc("baz", 11)
|
||||||
|
merge(t1, t2)
|
||||||
|
assert(t1["foo"] == 5)
|
||||||
|
assert(t1["bar"] == 3)
|
||||||
|
assert(t1["baz"] == 14)
|
||||||
|
|
||||||
|
let
|
||||||
|
t1r = newCountTable[string]()
|
||||||
|
t2r = newCountTable[string]()
|
||||||
|
t1r.inc("foo")
|
||||||
|
t1r.inc("bar", 2)
|
||||||
|
t1r.inc("baz", 3)
|
||||||
|
t2r.inc("foo", 4)
|
||||||
|
t2r.inc("bar")
|
||||||
|
t2r.inc("baz", 11)
|
||||||
|
merge(t1r, t2r)
|
||||||
|
assert(t1r["foo"] == 5)
|
||||||
|
assert(t1r["bar"] == 3)
|
||||||
|
assert(t1r["baz"] == 14)
|
||||||
|
|
||||||
|
var
|
||||||
|
t1l = initCountTable[string]()
|
||||||
|
t2l = initCountTable[string]()
|
||||||
|
t1l.inc("foo")
|
||||||
|
t1l.inc("bar", 2)
|
||||||
|
t1l.inc("baz", 3)
|
||||||
|
t2l.inc("foo", 4)
|
||||||
|
t2l.inc("bar")
|
||||||
|
t2l.inc("baz", 11)
|
||||||
|
|
||||||
|
block:
|
||||||
|
const testKey = "TESTKEY"
|
||||||
|
let t: CountTableRef[string] = newCountTable[string]()
|
||||||
|
|
||||||
|
# Before, does not compile with error message:
|
||||||
|
#test_counttable.nim(7, 43) template/generic instantiation from here
|
||||||
|
#lib/pure/collections/tables.nim(117, 21) template/generic instantiation from here
|
||||||
|
#lib/pure/collections/tableimpl.nim(32, 27) Error: undeclared field: 'hcode
|
||||||
|
doAssert 0 == t[testKey]
|
||||||
|
t.inc(testKey, 3)
|
||||||
|
doAssert 3 == t[testKey]
|
||||||
|
|
||||||
|
block:
|
||||||
|
# Clear tests
|
||||||
|
var clearTable = newTable[int, string]()
|
||||||
|
clearTable[42] = "asd"
|
||||||
|
clearTable[123123] = "piuyqwb "
|
||||||
|
doAssert clearTable[42] == "asd"
|
||||||
|
clearTable.clear()
|
||||||
|
doAssert(not clearTable.hasKey(123123))
|
||||||
|
doAssert clearTable.getOrDefault(42) == ""
|
||||||
|
|
||||||
|
block: #5482
|
||||||
|
var a = [("wrong?", "foo"), ("wrong?", "foo2")].newOrderedTable()
|
||||||
|
var b = newOrderedTable[string, string](initialSize = 2)
|
||||||
|
b["wrong?"] = "foo"
|
||||||
|
b["wrong?"] = "foo2"
|
||||||
|
assert a == b
|
||||||
|
|
||||||
|
block: #5482
|
||||||
|
var a = {"wrong?": "foo", "wrong?": "foo2"}.newOrderedTable()
|
||||||
|
var b = newOrderedTable[string, string](initialSize = 2)
|
||||||
|
b["wrong?"] = "foo"
|
||||||
|
b["wrong?"] = "foo2"
|
||||||
|
assert a == b
|
||||||
|
|
||||||
|
block: #5487
|
||||||
|
var a = {"wrong?": "foo", "wrong?": "foo2"}.newOrderedTable()
|
||||||
|
var b = newOrderedTable[string, string]() # notice, default size!
|
||||||
|
b["wrong?"] = "foo"
|
||||||
|
b["wrong?"] = "foo2"
|
||||||
|
assert a == b
|
||||||
|
|
||||||
|
block: #5487
|
||||||
|
var a = [("wrong?", "foo"), ("wrong?", "foo2")].newOrderedTable()
|
||||||
|
var b = newOrderedTable[string, string]() # notice, default size!
|
||||||
|
b["wrong?"] = "foo"
|
||||||
|
b["wrong?"] = "foo2"
|
||||||
|
assert a == b
|
||||||
|
|
||||||
|
block:
|
||||||
|
var a = {"wrong?": "foo", "wrong?": "foo2"}.newOrderedTable()
|
||||||
|
var b = [("wrong?", "foo"), ("wrong?", "foo2")].newOrderedTable()
|
||||||
|
var c = newOrderedTable[string, string]() # notice, default size!
|
||||||
|
c["wrong?"] = "foo"
|
||||||
|
c["wrong?"] = "foo2"
|
||||||
|
assert a == b
|
||||||
|
assert a == c
|
||||||
|
|
||||||
|
block: #6250
|
||||||
|
let
|
||||||
|
a = {3: 1}.toOrderedTable
|
||||||
|
b = {3: 2}.toOrderedTable
|
||||||
|
assert((a == b) == false)
|
||||||
|
assert((b == a) == false)
|
||||||
|
|
||||||
|
block: #6250
|
||||||
|
let
|
||||||
|
a = {3: 2}.toOrderedTable
|
||||||
|
b = {3: 2}.toOrderedTable
|
||||||
|
assert((a == b) == true)
|
||||||
|
assert((b == a) == true)
|
||||||
|
|
||||||
|
block: # CountTable.smallest
|
||||||
|
let t = toCountTable([0, 0, 5, 5, 5])
|
||||||
|
doAssert t.smallest == (0, 2)
|
||||||
|
|
||||||
|
block: #10065
|
||||||
|
let t = toCountTable("abracadabra")
|
||||||
|
doAssert t['z'] == 0
|
||||||
|
|
||||||
|
var t_mut = toCountTable("abracadabra")
|
||||||
|
doAssert t_mut['z'] == 0
|
||||||
|
# the previous read may not have modified the table.
|
||||||
|
doAssert t_mut.hasKey('z') == false
|
||||||
|
t_mut['z'] = 1
|
||||||
|
doAssert t_mut['z'] == 1
|
||||||
|
doAssert t_mut.hasKey('z') == true
|
||||||
|
|
||||||
|
block: #12813 #13079
|
||||||
|
var t = toCountTable("abracadabra")
|
||||||
|
doAssert len(t) == 5
|
||||||
|
|
||||||
|
t['a'] = 0 # remove a key
|
||||||
|
doAssert len(t) == 4
|
||||||
|
|
||||||
|
block:
|
||||||
|
var tp: Table[string, string] = initTable[string, string]()
|
||||||
|
doAssert "test1" == tp.getOrDefault("test1", "test1")
|
||||||
|
tp["test2"] = "test2"
|
||||||
|
doAssert "test2" == tp.getOrDefault("test2", "test1")
|
||||||
|
var tr: TableRef[string, string] = newTable[string, string]()
|
||||||
|
doAssert "test1" == tr.getOrDefault("test1", "test1")
|
||||||
|
tr["test2"] = "test2"
|
||||||
|
doAssert "test2" == tr.getOrDefault("test2", "test1")
|
||||||
|
var op: OrderedTable[string, string] = initOrderedTable[string, string]()
|
||||||
|
doAssert "test1" == op.getOrDefault("test1", "test1")
|
||||||
|
op["test2"] = "test2"
|
||||||
|
doAssert "test2" == op.getOrDefault("test2", "test1")
|
||||||
|
var orf: OrderedTableRef[string, string] = newOrderedTable[string, string]()
|
||||||
|
doAssert "test1" == orf.getOrDefault("test1", "test1")
|
||||||
|
orf["test2"] = "test2"
|
||||||
|
doAssert "test2" == orf.getOrDefault("test2", "test1")
|
||||||
|
|
||||||
|
block tableWithoutInit:
|
||||||
|
var
|
||||||
|
a: Table[string, int]
|
||||||
|
b: Table[string, int]
|
||||||
|
c: Table[string, int]
|
||||||
|
d: Table[string, int]
|
||||||
|
e: Table[string, int]
|
||||||
|
|
||||||
|
a["a"] = 7
|
||||||
|
doAssert a.hasKey("a")
|
||||||
|
doAssert a.len == 1
|
||||||
|
doAssert a["a"] == 7
|
||||||
|
a["a"] = 9
|
||||||
|
doAssert a.len == 1
|
||||||
|
doAssert a["a"] == 9
|
||||||
|
|
||||||
|
doAssert b.hasKeyOrPut("b", 5) == false
|
||||||
|
doAssert b.hasKey("b")
|
||||||
|
doAssert b.hasKeyOrPut("b", 8)
|
||||||
|
doAssert b["b"] == 5
|
||||||
|
|
||||||
|
doAssert c.getOrDefault("a") == 0
|
||||||
|
doAssert c.getOrDefault("a", 3) == 3
|
||||||
|
c["a"] = 6
|
||||||
|
doAssert c.getOrDefault("a", 3) == 6
|
||||||
|
|
||||||
|
doAssert d.mgetOrPut("a", 3) == 3
|
||||||
|
doAssert d.mgetOrPut("a", 6) == 3
|
||||||
|
|
||||||
|
var x = 99
|
||||||
|
doAssert e.pop("a", x) == false
|
||||||
|
doAssert x == 99
|
||||||
|
e["a"] = 77
|
||||||
|
doAssert e.pop("a", x)
|
||||||
|
doAssert x == 77
|
||||||
|
|
||||||
|
block orderedTableWithoutInit:
|
||||||
|
var
|
||||||
|
a: OrderedTable[string, int]
|
||||||
|
b: OrderedTable[string, int]
|
||||||
|
c: OrderedTable[string, int]
|
||||||
|
d: OrderedTable[string, int]
|
||||||
|
|
||||||
|
a["a"] = 7
|
||||||
|
doAssert a.hasKey("a")
|
||||||
|
doAssert a.len == 1
|
||||||
|
doAssert a["a"] == 7
|
||||||
|
a["a"] = 9
|
||||||
|
doAssert a.len == 1
|
||||||
|
doAssert a["a"] == 9
|
||||||
|
|
||||||
|
doAssert b.hasKeyOrPut("b", 5) == false
|
||||||
|
doAssert b.hasKey("b")
|
||||||
|
doAssert b.hasKeyOrPut("b", 8)
|
||||||
|
doAssert b["b"] == 5
|
||||||
|
|
||||||
|
doAssert c.getOrDefault("a") == 0
|
||||||
|
doAssert c.getOrDefault("a", 3) == 3
|
||||||
|
c["a"] = 6
|
||||||
|
doAssert c.getOrDefault("a", 3) == 6
|
||||||
|
|
||||||
|
doAssert d.mgetOrPut("a", 3) == 3
|
||||||
|
doAssert d.mgetOrPut("a", 6) == 3
|
||||||
|
|
||||||
|
block countTableWithoutInit:
|
||||||
|
var
|
||||||
|
a: CountTable[string]
|
||||||
|
b: CountTable[string]
|
||||||
|
c: CountTable[string]
|
||||||
|
d: CountTable[string]
|
||||||
|
e: CountTable[string]
|
||||||
|
|
||||||
|
a["a"] = 7
|
||||||
|
doAssert a.hasKey("a")
|
||||||
|
doAssert a.len == 1
|
||||||
|
doAssert a["a"] == 7
|
||||||
|
a["a"] = 9
|
||||||
|
doAssert a.len == 1
|
||||||
|
doAssert a["a"] == 9
|
||||||
|
|
||||||
|
doAssert b["b"] == 0
|
||||||
|
b.inc("b")
|
||||||
|
doAssert b["b"] == 1
|
||||||
|
|
||||||
|
doAssert c.getOrDefault("a") == 0
|
||||||
|
doAssert c.getOrDefault("a", 3) == 3
|
||||||
|
c["a"] = 6
|
||||||
|
doAssert c.getOrDefault("a", 3) == 6
|
||||||
|
|
||||||
|
e["f"] = 3
|
||||||
|
merge(d, e)
|
||||||
|
doAssert d.hasKey("f")
|
||||||
|
d.inc("f")
|
||||||
|
merge(d, e)
|
||||||
|
doAssert d["f"] == 7
|
||||||
215
tests/stdlib/tunicode.nim
Normal file
215
tests/stdlib/tunicode.nim
Normal file
|
|
@ -0,0 +1,215 @@
|
||||||
|
import unicode
|
||||||
|
|
||||||
|
|
||||||
|
proc asRune(s: static[string]): Rune =
|
||||||
|
## Compile-time conversion proc for converting string literals to a Rune
|
||||||
|
## value. Returns the first Rune of the specified string.
|
||||||
|
##
|
||||||
|
## Shortcuts code like ``"å".runeAt(0)`` to ``"å".asRune`` and returns a
|
||||||
|
## compile-time constant.
|
||||||
|
if s.len == 0: Rune(0)
|
||||||
|
else: s.runeAt(0)
|
||||||
|
|
||||||
|
let
|
||||||
|
someString = "öÑ"
|
||||||
|
someRunes = toRunes(someString)
|
||||||
|
compared = (someString == $someRunes)
|
||||||
|
doAssert compared == true
|
||||||
|
|
||||||
|
proc testReplacements(word: string): string =
|
||||||
|
case word
|
||||||
|
of "two":
|
||||||
|
return "2"
|
||||||
|
of "foo":
|
||||||
|
return "BAR"
|
||||||
|
of "βeta":
|
||||||
|
return "beta"
|
||||||
|
of "alpha":
|
||||||
|
return "αlpha"
|
||||||
|
else:
|
||||||
|
return "12345"
|
||||||
|
|
||||||
|
doAssert translate("two not alpha foo βeta", testReplacements) == "2 12345 αlpha BAR beta"
|
||||||
|
doAssert translate(" two not foo βeta ", testReplacements) == " 2 12345 BAR beta "
|
||||||
|
|
||||||
|
doAssert title("foo bar") == "Foo Bar"
|
||||||
|
doAssert title("αlpha βeta γamma") == "Αlpha Βeta Γamma"
|
||||||
|
doAssert title("") == ""
|
||||||
|
|
||||||
|
doAssert capitalize("βeta") == "Βeta"
|
||||||
|
doAssert capitalize("foo") == "Foo"
|
||||||
|
doAssert capitalize("") == ""
|
||||||
|
|
||||||
|
doAssert swapCase("FooBar") == "fOObAR"
|
||||||
|
doAssert swapCase(" ") == " "
|
||||||
|
doAssert swapCase("Αlpha Βeta Γamma") == "αLPHA βETA γAMMA"
|
||||||
|
doAssert swapCase("a✓B") == "A✓b"
|
||||||
|
doAssert swapCase("Јамогујестистаклоитоминештети") == "јАМОГУЈЕСТИСТАКЛОИТОМИНЕШТЕТИ"
|
||||||
|
doAssert swapCase("ὕαλονϕαγεῖνδύναμαιτοῦτοοὔμεβλάπτει") == "ὝΑΛΟΝΦΑΓΕῖΝΔΎΝΑΜΑΙΤΟῦΤΟΟὔΜΕΒΛΆΠΤΕΙ"
|
||||||
|
doAssert swapCase("Կրնամապակիուտեևինծիանհանգիստչըներ") == "կՐՆԱՄԱՊԱԿԻՈՒՏԵևԻՆԾԻԱՆՀԱՆԳԻՍՏՉԸՆԵՐ"
|
||||||
|
doAssert swapCase("") == ""
|
||||||
|
|
||||||
|
doAssert isAlpha("r")
|
||||||
|
doAssert isAlpha("α")
|
||||||
|
doAssert isAlpha("ϙ")
|
||||||
|
doAssert isAlpha("ஶ")
|
||||||
|
doAssert(not isAlpha("$"))
|
||||||
|
doAssert(not isAlpha(""))
|
||||||
|
|
||||||
|
doAssert isAlpha("Βeta")
|
||||||
|
doAssert isAlpha("Args")
|
||||||
|
doAssert isAlpha("𐌼𐌰𐌲𐌲𐌻𐌴𐍃𐍄𐌰𐌽")
|
||||||
|
doAssert isAlpha("ὕαλονϕαγεῖνδύναμαιτοῦτοοὔμεβλάπτει")
|
||||||
|
doAssert isAlpha("Јамогујестистаклоитоминештети")
|
||||||
|
doAssert isAlpha("Կրնամապակիուտեևինծիանհանգիստչըներ")
|
||||||
|
doAssert(not isAlpha("$Foo✓"))
|
||||||
|
doAssert(not isAlpha("⠙⠕⠑⠎⠝⠞"))
|
||||||
|
|
||||||
|
doAssert isSpace("\t")
|
||||||
|
doAssert isSpace("\l")
|
||||||
|
doAssert(not isSpace("Β"))
|
||||||
|
doAssert(not isSpace("Βeta"))
|
||||||
|
|
||||||
|
doAssert isSpace("\t\l \v\r\f")
|
||||||
|
doAssert isSpace(" ")
|
||||||
|
doAssert(not isSpace(""))
|
||||||
|
doAssert(not isSpace("ΑΓc \td"))
|
||||||
|
|
||||||
|
doAssert(not isLower(' '.Rune))
|
||||||
|
|
||||||
|
doAssert(not isUpper(' '.Rune))
|
||||||
|
|
||||||
|
doAssert toUpper("Γ") == "Γ"
|
||||||
|
doAssert toUpper("b") == "B"
|
||||||
|
doAssert toUpper("α") == "Α"
|
||||||
|
doAssert toUpper("✓") == "✓"
|
||||||
|
doAssert toUpper("ϙ") == "Ϙ"
|
||||||
|
doAssert toUpper("") == ""
|
||||||
|
|
||||||
|
doAssert toUpper("ΑΒΓ") == "ΑΒΓ"
|
||||||
|
doAssert toUpper("AAccβ") == "AACCΒ"
|
||||||
|
doAssert toUpper("A✓$β") == "A✓$Β"
|
||||||
|
|
||||||
|
doAssert toLower("a") == "a"
|
||||||
|
doAssert toLower("γ") == "γ"
|
||||||
|
doAssert toLower("Γ") == "γ"
|
||||||
|
doAssert toLower("4") == "4"
|
||||||
|
doAssert toLower("Ϙ") == "ϙ"
|
||||||
|
doAssert toLower("") == ""
|
||||||
|
|
||||||
|
doAssert toLower("abcdγ") == "abcdγ"
|
||||||
|
doAssert toLower("abCDΓ") == "abcdγ"
|
||||||
|
doAssert toLower("33aaΓ") == "33aaγ"
|
||||||
|
|
||||||
|
doAssert reversed("Reverse this!") == "!siht esreveR"
|
||||||
|
doAssert reversed("先秦兩漢") == "漢兩秦先"
|
||||||
|
doAssert reversed("as⃝df̅") == "f̅ds⃝a"
|
||||||
|
doAssert reversed("a⃞b⃞c⃞") == "c⃞b⃞a⃞"
|
||||||
|
doAssert reversed("ὕαλονϕαγεῖνδύναμαιτοῦτοοὔμεβλάπτει") == "ιετπάλβεμὔοοτῦοτιαμανύδνῖεγαϕνολαὕ"
|
||||||
|
doAssert reversed("Јамогујестистаклоитоминештети") == "итетшенимотиолкатситсејугомаЈ"
|
||||||
|
doAssert reversed("Կրնամապակիուտեևինծիանհանգիստչըներ") == "րենըչտսիգնահնաիծնիևետւոիկապամանրԿ"
|
||||||
|
doAssert len(toRunes("as⃝df̅")) == runeLen("as⃝df̅")
|
||||||
|
const test = "as⃝"
|
||||||
|
doAssert lastRune(test, test.len-1)[1] == 3
|
||||||
|
doAssert graphemeLen("è", 0) == 2
|
||||||
|
|
||||||
|
# test for rune positioning and runeSubStr()
|
||||||
|
let s = "Hänsel ««: 10,00€"
|
||||||
|
|
||||||
|
var t = ""
|
||||||
|
for c in s.utf8:
|
||||||
|
t.add c
|
||||||
|
|
||||||
|
doAssert(s == t)
|
||||||
|
|
||||||
|
doAssert(runeReverseOffset(s, 1) == (20, 18))
|
||||||
|
doAssert(runeReverseOffset(s, 19) == (-1, 18))
|
||||||
|
|
||||||
|
doAssert(runeStrAtPos(s, 0) == "H")
|
||||||
|
doAssert(runeSubStr(s, 0, 1) == "H")
|
||||||
|
doAssert(runeStrAtPos(s, 10) == ":")
|
||||||
|
doAssert(runeSubStr(s, 10, 1) == ":")
|
||||||
|
doAssert(runeStrAtPos(s, 9) == "«")
|
||||||
|
doAssert(runeSubStr(s, 9, 1) == "«")
|
||||||
|
doAssert(runeStrAtPos(s, 17) == "€")
|
||||||
|
doAssert(runeSubStr(s, 17, 1) == "€")
|
||||||
|
# echo runeStrAtPos(s, 18) # index error
|
||||||
|
|
||||||
|
doAssert(runeSubStr(s, 0) == "Hänsel ««: 10,00€")
|
||||||
|
doAssert(runeSubStr(s, -18) == "Hänsel ««: 10,00€")
|
||||||
|
doAssert(runeSubStr(s, 10) == ": 10,00€")
|
||||||
|
doAssert(runeSubStr(s, 18) == "")
|
||||||
|
doAssert(runeSubStr(s, 0, 10) == "Hänsel ««")
|
||||||
|
|
||||||
|
doAssert(runeSubStr(s, 12) == "10,00€")
|
||||||
|
doAssert(runeSubStr(s, -6) == "10,00€")
|
||||||
|
|
||||||
|
doAssert(runeSubStr(s, 12, 5) == "10,00")
|
||||||
|
doAssert(runeSubStr(s, 12, -1) == "10,00")
|
||||||
|
doAssert(runeSubStr(s, -6, 5) == "10,00")
|
||||||
|
doAssert(runeSubStr(s, -6, -1) == "10,00")
|
||||||
|
|
||||||
|
doAssert(runeSubStr(s, 0, 100) == "Hänsel ««: 10,00€")
|
||||||
|
doAssert(runeSubStr(s, -100, 100) == "Hänsel ««: 10,00€")
|
||||||
|
doAssert(runeSubStr(s, 0, -100) == "")
|
||||||
|
doAssert(runeSubStr(s, 100, -100) == "")
|
||||||
|
|
||||||
|
block splitTests:
|
||||||
|
let s = " this is an example "
|
||||||
|
let s2 = ":this;is;an:example;;"
|
||||||
|
let s3 = ":this×is×an:example××"
|
||||||
|
doAssert s.split() == @["", "this", "is", "an", "example", "", ""]
|
||||||
|
doAssert s2.split(seps = [':'.Rune, ';'.Rune]) == @["", "this", "is", "an",
|
||||||
|
"example", "", ""]
|
||||||
|
doAssert s3.split(seps = [':'.Rune, "×".asRune]) == @["", "this", "is",
|
||||||
|
"an", "example", "", ""]
|
||||||
|
doAssert s.split(maxsplit = 4) == @["", "this", "is", "an", "example "]
|
||||||
|
doAssert s.split(' '.Rune, maxsplit = 1) == @["", "this is an example "]
|
||||||
|
doAssert s3.split("×".runeAt(0)) == @[":this", "is", "an:example", "", ""]
|
||||||
|
|
||||||
|
block stripTests:
|
||||||
|
doAssert(strip("") == "")
|
||||||
|
doAssert(strip(" ") == "")
|
||||||
|
doAssert(strip("y") == "y")
|
||||||
|
doAssert(strip(" foofoofoo ") == "foofoofoo")
|
||||||
|
doAssert(strip("sfoofoofoos", runes = ['s'.Rune]) == "foofoofoo")
|
||||||
|
|
||||||
|
block:
|
||||||
|
let stripTestRunes = ['b'.Rune, 'a'.Rune, 'r'.Rune]
|
||||||
|
doAssert(strip("barfoofoofoobar", runes = stripTestRunes) == "foofoofoo")
|
||||||
|
doAssert(strip("sfoofoofoos", leading = false, runes = ['s'.Rune]) == "sfoofoofoo")
|
||||||
|
doAssert(strip("sfoofoofoos", trailing = false, runes = ['s'.Rune]) == "foofoofoos")
|
||||||
|
|
||||||
|
block:
|
||||||
|
let stripTestRunes = ["«".asRune, "»".asRune]
|
||||||
|
doAssert(strip("«TEXT»", runes = stripTestRunes) == "TEXT")
|
||||||
|
doAssert(strip("copyright©", leading = false, runes = ["©".asRune]) == "copyright")
|
||||||
|
doAssert(strip("¿Question?", trailing = false, runes = ["¿".asRune]) == "Question?")
|
||||||
|
doAssert(strip("×text×", leading = false, runes = ["×".asRune]) == "×text")
|
||||||
|
doAssert(strip("×text×", trailing = false, runes = ["×".asRune]) == "text×")
|
||||||
|
|
||||||
|
block repeatTests:
|
||||||
|
doAssert repeat('c'.Rune, 5) == "ccccc"
|
||||||
|
doAssert repeat("×".asRune, 5) == "×××××"
|
||||||
|
|
||||||
|
block alignTests:
|
||||||
|
doAssert align("abc", 4) == " abc"
|
||||||
|
doAssert align("a", 0) == "a"
|
||||||
|
doAssert align("1232", 6) == " 1232"
|
||||||
|
doAssert align("1232", 6, '#'.Rune) == "##1232"
|
||||||
|
doAssert align("1232", 6, "×".asRune) == "××1232"
|
||||||
|
doAssert alignLeft("abc", 4) == "abc "
|
||||||
|
doAssert alignLeft("a", 0) == "a"
|
||||||
|
doAssert alignLeft("1232", 6) == "1232 "
|
||||||
|
doAssert alignLeft("1232", 6, '#'.Rune) == "1232##"
|
||||||
|
doAssert alignLeft("1232", 6, "×".asRune) == "1232××"
|
||||||
|
|
||||||
|
block differentSizes:
|
||||||
|
# upper and lower variants have different number of bytes
|
||||||
|
doAssert toLower("AẞC") == "aßc"
|
||||||
|
doAssert toLower("ȺẞCD") == "ⱥßcd"
|
||||||
|
doAssert toUpper("ⱥbc") == "ȺBC"
|
||||||
|
doAssert toUpper("rsⱦuv") == "RSȾUV"
|
||||||
|
doAssert swapCase("ⱥbCd") == "ȺBcD"
|
||||||
|
doAssert swapCase("XyꟆaB") == "xYᶎAb"
|
||||||
|
doAssert swapCase("aᵹcᲈd") == "AꝽCꙊD"
|
||||||
|
|
@ -9,6 +9,5 @@ import std/unidecode # #14112
|
||||||
|
|
||||||
loadUnidecodeTable("lib/pure/unidecode/unidecode.dat")
|
loadUnidecodeTable("lib/pure/unidecode/unidecode.dat")
|
||||||
|
|
||||||
#assert unidecode("\x53\x17\x4E\xB0") == "Bei Jing"
|
# assert unidecode("\x53\x17\x4E\xB0") == "Bei Jing"
|
||||||
echo unidecode("Äußerst")
|
echo unidecode("Äußerst")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ discard """
|
||||||
exitcode: 0
|
exitcode: 0
|
||||||
timeout: 60.0
|
timeout: 60.0
|
||||||
"""
|
"""
|
||||||
import uri
|
include uri
|
||||||
|
|
||||||
|
|
||||||
block:
|
block:
|
||||||
|
|
@ -15,3 +15,286 @@ block:
|
||||||
doAssert url.hostname == "2001:0db8:85a3:0000:0000:8a2e:0370:7334" # true
|
doAssert url.hostname == "2001:0db8:85a3:0000:0000:8a2e:0370:7334" # true
|
||||||
let newUrl = parseUri($url)
|
let newUrl = parseUri($url)
|
||||||
doAssert newUrl.hostname == "2001:0db8:85a3:0000:0000:8a2e:0370:7334" # true
|
doAssert newUrl.hostname == "2001:0db8:85a3:0000:0000:8a2e:0370:7334" # true
|
||||||
|
|
||||||
|
|
||||||
|
block:
|
||||||
|
block:
|
||||||
|
const test1 = "abc\L+def xyz"
|
||||||
|
doAssert encodeUrl(test1) == "abc%0A%2Bdef+xyz"
|
||||||
|
doAssert decodeUrl(encodeUrl(test1)) == test1
|
||||||
|
doAssert encodeUrl(test1, false) == "abc%0A%2Bdef%20xyz"
|
||||||
|
doAssert decodeUrl(encodeUrl(test1, false), false) == test1
|
||||||
|
doAssert decodeUrl(encodeUrl(test1)) == test1
|
||||||
|
|
||||||
|
block:
|
||||||
|
let str = "http://localhost"
|
||||||
|
let test = parseUri(str)
|
||||||
|
doAssert test.path == ""
|
||||||
|
|
||||||
|
block:
|
||||||
|
let str = "http://localhost/"
|
||||||
|
let test = parseUri(str)
|
||||||
|
doAssert test.path == "/"
|
||||||
|
|
||||||
|
block:
|
||||||
|
let str = "http://localhost:8080/test"
|
||||||
|
let test = parseUri(str)
|
||||||
|
doAssert test.scheme == "http"
|
||||||
|
doAssert test.port == "8080"
|
||||||
|
doAssert test.path == "/test"
|
||||||
|
doAssert test.hostname == "localhost"
|
||||||
|
doAssert($test == str)
|
||||||
|
|
||||||
|
block:
|
||||||
|
let str = "foo://username:password@example.com:8042/over/there" &
|
||||||
|
"/index.dtb?type=animal&name=narwhal#nose"
|
||||||
|
let test = parseUri(str)
|
||||||
|
doAssert test.scheme == "foo"
|
||||||
|
doAssert test.username == "username"
|
||||||
|
doAssert test.password == "password"
|
||||||
|
doAssert test.hostname == "example.com"
|
||||||
|
doAssert test.port == "8042"
|
||||||
|
doAssert test.path == "/over/there/index.dtb"
|
||||||
|
doAssert test.query == "type=animal&name=narwhal"
|
||||||
|
doAssert test.anchor == "nose"
|
||||||
|
doAssert($test == str)
|
||||||
|
|
||||||
|
block:
|
||||||
|
# IPv6 address
|
||||||
|
let str = "foo://[::1]:1234/bar?baz=true&qux#quux"
|
||||||
|
let uri = parseUri(str)
|
||||||
|
doAssert uri.scheme == "foo"
|
||||||
|
doAssert uri.hostname == "::1"
|
||||||
|
doAssert uri.port == "1234"
|
||||||
|
doAssert uri.path == "/bar"
|
||||||
|
doAssert uri.query == "baz=true&qux"
|
||||||
|
doAssert uri.anchor == "quux"
|
||||||
|
|
||||||
|
block:
|
||||||
|
let str = "urn:example:animal:ferret:nose"
|
||||||
|
let test = parseUri(str)
|
||||||
|
doAssert test.scheme == "urn"
|
||||||
|
doAssert test.path == "example:animal:ferret:nose"
|
||||||
|
doAssert($test == str)
|
||||||
|
|
||||||
|
block:
|
||||||
|
let str = "mailto:username@example.com?subject=Topic"
|
||||||
|
let test = parseUri(str)
|
||||||
|
doAssert test.scheme == "mailto"
|
||||||
|
doAssert test.username == "username"
|
||||||
|
doAssert test.hostname == "example.com"
|
||||||
|
doAssert test.query == "subject=Topic"
|
||||||
|
doAssert($test == str)
|
||||||
|
|
||||||
|
block:
|
||||||
|
let str = "magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
|
||||||
|
let test = parseUri(str)
|
||||||
|
doAssert test.scheme == "magnet"
|
||||||
|
doAssert test.query == "xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
|
||||||
|
doAssert($test == str)
|
||||||
|
|
||||||
|
block:
|
||||||
|
let str = "/test/foo/bar?q=2#asdf"
|
||||||
|
let test = parseUri(str)
|
||||||
|
doAssert test.scheme == ""
|
||||||
|
doAssert test.path == "/test/foo/bar"
|
||||||
|
doAssert test.query == "q=2"
|
||||||
|
doAssert test.anchor == "asdf"
|
||||||
|
doAssert($test == str)
|
||||||
|
|
||||||
|
block:
|
||||||
|
let str = "test/no/slash"
|
||||||
|
let test = parseUri(str)
|
||||||
|
doAssert test.path == "test/no/slash"
|
||||||
|
doAssert($test == str)
|
||||||
|
|
||||||
|
block:
|
||||||
|
let str = "//git@github.com:dom96/packages"
|
||||||
|
let test = parseUri(str)
|
||||||
|
doAssert test.scheme == ""
|
||||||
|
doAssert test.username == "git"
|
||||||
|
doAssert test.hostname == "github.com"
|
||||||
|
doAssert test.port == "dom96"
|
||||||
|
doAssert test.path == "/packages"
|
||||||
|
|
||||||
|
block:
|
||||||
|
let str = "file:///foo/bar/baz.txt"
|
||||||
|
let test = parseUri(str)
|
||||||
|
doAssert test.scheme == "file"
|
||||||
|
doAssert test.username == ""
|
||||||
|
doAssert test.hostname == ""
|
||||||
|
doAssert test.port == ""
|
||||||
|
doAssert test.path == "/foo/bar/baz.txt"
|
||||||
|
|
||||||
|
# Remove dot segments tests
|
||||||
|
block:
|
||||||
|
doAssert removeDotSegments("/foo/bar/baz") == "/foo/bar/baz"
|
||||||
|
|
||||||
|
# Combine tests
|
||||||
|
block:
|
||||||
|
let concat = combine(parseUri("http://google.com/foo/bar/"), parseUri("baz"))
|
||||||
|
doAssert concat.path == "/foo/bar/baz"
|
||||||
|
doAssert concat.hostname == "google.com"
|
||||||
|
doAssert concat.scheme == "http"
|
||||||
|
|
||||||
|
block:
|
||||||
|
let concat = combine(parseUri("http://google.com/foo"), parseUri("/baz"))
|
||||||
|
doAssert concat.path == "/baz"
|
||||||
|
doAssert concat.hostname == "google.com"
|
||||||
|
doAssert concat.scheme == "http"
|
||||||
|
|
||||||
|
block:
|
||||||
|
let concat = combine(parseUri("http://google.com/foo/test"), parseUri("bar"))
|
||||||
|
doAssert concat.path == "/foo/bar"
|
||||||
|
|
||||||
|
block:
|
||||||
|
let concat = combine(parseUri("http://google.com/foo/test"), parseUri("/bar"))
|
||||||
|
doAssert concat.path == "/bar"
|
||||||
|
|
||||||
|
block:
|
||||||
|
let concat = combine(parseUri("http://google.com/foo/test"), parseUri("bar"))
|
||||||
|
doAssert concat.path == "/foo/bar"
|
||||||
|
|
||||||
|
block:
|
||||||
|
let concat = combine(parseUri("http://google.com/foo/test/"), parseUri("bar"))
|
||||||
|
doAssert concat.path == "/foo/test/bar"
|
||||||
|
|
||||||
|
block:
|
||||||
|
let concat = combine(parseUri("http://google.com/foo/test/"), parseUri("bar/"))
|
||||||
|
doAssert concat.path == "/foo/test/bar/"
|
||||||
|
|
||||||
|
block:
|
||||||
|
let concat = combine(parseUri("http://google.com/foo/test/"), parseUri("bar/"),
|
||||||
|
parseUri("baz"))
|
||||||
|
doAssert concat.path == "/foo/test/bar/baz"
|
||||||
|
|
||||||
|
# `/` tests
|
||||||
|
block:
|
||||||
|
let test = parseUri("http://example.com/foo") / "bar/asd"
|
||||||
|
doAssert test.path == "/foo/bar/asd"
|
||||||
|
|
||||||
|
block:
|
||||||
|
let test = parseUri("http://example.com/foo/") / "/bar/asd"
|
||||||
|
doAssert test.path == "/foo/bar/asd"
|
||||||
|
|
||||||
|
# removeDotSegments tests
|
||||||
|
block:
|
||||||
|
# empty test
|
||||||
|
doAssert removeDotSegments("") == ""
|
||||||
|
|
||||||
|
# bug #3207
|
||||||
|
block:
|
||||||
|
doAssert parseUri("http://qq/1").combine(parseUri("https://qqq")).`$` == "https://qqq"
|
||||||
|
|
||||||
|
# bug #4959
|
||||||
|
block:
|
||||||
|
let foo = parseUri("http://example.com") / "/baz"
|
||||||
|
doAssert foo.path == "/baz"
|
||||||
|
|
||||||
|
# bug found on stream 13/10/17
|
||||||
|
block:
|
||||||
|
let foo = parseUri("http://localhost:9515") / "status"
|
||||||
|
doAssert $foo == "http://localhost:9515/status"
|
||||||
|
|
||||||
|
# bug #6649 #6652
|
||||||
|
block:
|
||||||
|
var foo = parseUri("http://example.com")
|
||||||
|
foo.hostname = "example.com"
|
||||||
|
foo.path = "baz"
|
||||||
|
doAssert $foo == "http://example.com/baz"
|
||||||
|
|
||||||
|
foo.hostname = "example.com/"
|
||||||
|
foo.path = "baz"
|
||||||
|
doAssert $foo == "http://example.com/baz"
|
||||||
|
|
||||||
|
foo.hostname = "example.com"
|
||||||
|
foo.path = "/baz"
|
||||||
|
doAssert $foo == "http://example.com/baz"
|
||||||
|
|
||||||
|
foo.hostname = "example.com/"
|
||||||
|
foo.path = "/baz"
|
||||||
|
doAssert $foo == "http://example.com/baz"
|
||||||
|
|
||||||
|
foo.hostname = "example.com/"
|
||||||
|
foo.port = "8000"
|
||||||
|
foo.path = "baz"
|
||||||
|
doAssert $foo == "http://example.com:8000/baz"
|
||||||
|
|
||||||
|
foo = parseUri("file:/dir/file")
|
||||||
|
foo.path = "relative"
|
||||||
|
doAssert $foo == "file:relative"
|
||||||
|
|
||||||
|
# isAbsolute tests
|
||||||
|
block:
|
||||||
|
doAssert "www.google.com".parseUri().isAbsolute() == false
|
||||||
|
doAssert "http://www.google.com".parseUri().isAbsolute() == true
|
||||||
|
doAssert "file:/dir/file".parseUri().isAbsolute() == true
|
||||||
|
doAssert "file://localhost/dir/file".parseUri().isAbsolute() == true
|
||||||
|
doAssert "urn:ISSN:1535-3613".parseUri().isAbsolute() == true
|
||||||
|
|
||||||
|
# path-relative URL *relative
|
||||||
|
doAssert "about".parseUri().isAbsolute == false
|
||||||
|
doAssert "about/staff.html".parseUri().isAbsolute == false
|
||||||
|
doAssert "about/staff.html?".parseUri().isAbsolute == false
|
||||||
|
doAssert "about/staff.html?parameters".parseUri().isAbsolute == false
|
||||||
|
|
||||||
|
# absolute-path-relative URL *relative
|
||||||
|
doAssert "/".parseUri().isAbsolute == false
|
||||||
|
doAssert "/about".parseUri().isAbsolute == false
|
||||||
|
doAssert "/about/staff.html".parseUri().isAbsolute == false
|
||||||
|
doAssert "/about/staff.html?".parseUri().isAbsolute == false
|
||||||
|
doAssert "/about/staff.html?parameters".parseUri().isAbsolute == false
|
||||||
|
|
||||||
|
# scheme-relative URL *relative
|
||||||
|
doAssert "//username:password@example.com:8888".parseUri().isAbsolute == false
|
||||||
|
doAssert "//username@example.com".parseUri().isAbsolute == false
|
||||||
|
doAssert "//example.com".parseUri().isAbsolute == false
|
||||||
|
doAssert "//example.com/".parseUri().isAbsolute == false
|
||||||
|
doAssert "//example.com/about".parseUri().isAbsolute == false
|
||||||
|
doAssert "//example.com/about/staff.html".parseUri().isAbsolute == false
|
||||||
|
doAssert "//example.com/about/staff.html?".parseUri().isAbsolute == false
|
||||||
|
doAssert "//example.com/about/staff.html?parameters".parseUri().isAbsolute == false
|
||||||
|
|
||||||
|
# absolute URL *absolute
|
||||||
|
doAssert "https://username:password@example.com:8888".parseUri().isAbsolute == true
|
||||||
|
doAssert "https://username@example.com".parseUri().isAbsolute == true
|
||||||
|
doAssert "https://example.com".parseUri().isAbsolute == true
|
||||||
|
doAssert "https://example.com/".parseUri().isAbsolute == true
|
||||||
|
doAssert "https://example.com/about".parseUri().isAbsolute == true
|
||||||
|
doAssert "https://example.com/about/staff.html".parseUri().isAbsolute == true
|
||||||
|
doAssert "https://example.com/about/staff.html?".parseUri().isAbsolute == true
|
||||||
|
doAssert "https://example.com/about/staff.html?parameters".parseUri().isAbsolute == true
|
||||||
|
|
||||||
|
# encodeQuery tests
|
||||||
|
block:
|
||||||
|
doAssert encodeQuery({:}) == ""
|
||||||
|
doAssert encodeQuery({"foo": "bar"}) == "foo=bar"
|
||||||
|
doAssert encodeQuery({"foo": "bar & baz"}) == "foo=bar+%26+baz"
|
||||||
|
doAssert encodeQuery({"foo": "bar & baz"}, usePlus = false) == "foo=bar%20%26%20baz"
|
||||||
|
doAssert encodeQuery({"foo": ""}) == "foo"
|
||||||
|
doAssert encodeQuery({"foo": ""}, omitEq = false) == "foo="
|
||||||
|
doAssert encodeQuery({"a": "1", "b": "", "c": "3"}) == "a=1&b&c=3"
|
||||||
|
doAssert encodeQuery({"a": "1", "b": "", "c": "3"}, omitEq = false) == "a=1&b=&c=3"
|
||||||
|
|
||||||
|
block:
|
||||||
|
var foo = parseUri("http://example.com") / "foo" ? {"bar": "1", "baz": "qux"}
|
||||||
|
var foo1 = parseUri("http://example.com/foo?bar=1&baz=qux")
|
||||||
|
doAssert foo == foo1
|
||||||
|
|
||||||
|
block:
|
||||||
|
var foo = parseUri("http://example.com") / "foo" ? {"do": "do", "bar": ""}
|
||||||
|
var foo1 = parseUri("http://example.com/foo?do=do&bar")
|
||||||
|
doAssert foo == foo1
|
||||||
|
|
||||||
|
block dataUriBase64:
|
||||||
|
doAssert getDataUri("", "text/plain") == "data:text/plain;charset=utf-8;base64,"
|
||||||
|
doAssert getDataUri(" ", "text/plain") == "data:text/plain;charset=utf-8;base64,IA=="
|
||||||
|
doAssert getDataUri("c\xf7>", "text/plain") == "data:text/plain;charset=utf-8;base64,Y/c+"
|
||||||
|
doAssert getDataUri("Hello World", "text/plain") == "data:text/plain;charset=utf-8;base64,SGVsbG8gV29ybGQ="
|
||||||
|
doAssert getDataUri("leasure.", "text/plain") == "data:text/plain;charset=utf-8;base64,bGVhc3VyZS4="
|
||||||
|
doAssert getDataUri("""!@#$%^&*()_+""", "text/plain") == "data:text/plain;charset=utf-8;base64,IUAjJCVeJiooKV8r"
|
||||||
|
doAssert(getDataUri("the quick brown dog jumps over the lazy fox", "text/plain") ==
|
||||||
|
"data:text/plain;charset=utf-8;base64,dGhlIHF1aWNrIGJyb3duIGRvZyBqdW1wcyBvdmVyIHRoZSBsYXp5IGZveA==")
|
||||||
|
doAssert(getDataUri("""The present is theirs
|
||||||
|
The future, for which I really worked, is mine.""", "text/plain") ==
|
||||||
|
"data:text/plain;charset=utf-8;base64,VGhlIHByZXNlbnQgaXMgdGhlaXJzCiAgICAgIFRoZSBmdXR1cmUsIGZvciB3aGljaCBJIHJlYWxseSB3b3JrZWQsIGlzIG1pbmUu")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue