diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index ff835b57a01a..2430e7330c2c 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -665,36 +665,6 @@ proc prevPermutation*[T](x: var openArray[T]): bool {.discardable.} = 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 = ## A port of std::rotate from c++. Ported from `this reference `_. result = first + last - middle @@ -852,71 +822,3 @@ proc rotatedLeft*[T](arg: openArray[T]; dist: int): seq[T] = let arglen = arg.len let distLeft = ((dist mod arglen) + arglen) mod arglen 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 diff --git a/lib/pure/collections/critbits.nim b/lib/pure/collections/critbits.nim index 4611c25402f2..695f446460b0 100644 --- a/lib/pure/collections/critbits.nim +++ b/lib/pure/collections/critbits.nim @@ -567,66 +567,3 @@ runnableExamples: doAssert critbitAsDict["key"] == -int.high 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" diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index e94e2a00b098..a0efcdce2e86 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -2873,317 +2873,3 @@ iterator mvalues*[A](t: CountTableRef[A]): var int = if t.data[h].val != 0: yield t.data[h].val 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 diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim index eaff86ae6aa8..7e686d44fafb 100644 --- a/lib/pure/cookies.nim +++ b/lib/pure/cookies.nim @@ -59,18 +59,3 @@ proc setCookie*(key, value: string, expires: DateTime|Time, return setCookie(key, value, domain, path, format(expires.utc, "ddd',' dd MMM yyyy HH:mm:ss 'GMT'"), 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" diff --git a/lib/pure/fenv.nim b/lib/pure/fenv.nim index 53b3e3b50806..abddaf4cbd83 100644 --- a/lib/pure/fenv.nim +++ b/lib/pure/fenv.nim @@ -178,11 +178,3 @@ template maximumPositiveValue*(T: typedesc[float64]): float64 = DBL_MAX template epsilon*(T: typedesc[float64]): float64 = DBL_EPSILON ## The difference between 1.0 and the smallest number greater than ## 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) diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim index 3191d4030538..667f27e95d2e 100644 --- a/lib/pure/hashes.nim +++ b/lib/pure/hashes.nim @@ -485,46 +485,3 @@ proc hash*[A](x: set[A]): Hash = for it in items(x): result = result !& hash(it) 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) diff --git a/lib/pure/httpcore.nim b/lib/pure/httpcore.nim index 401e78b9b368..7ead64d838e7 100644 --- a/lib/pure/httpcore.nim +++ b/lib/pure/httpcore.nim @@ -345,28 +345,3 @@ func is5xx*(code: HttpCode): bool {.inline.} = func `$`*(httpMethod: HttpMethod): string = 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" diff --git a/lib/pure/math.nim b/lib/pure/math.nim index 59368fbd28c6..af31a578512e 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -1101,128 +1101,3 @@ proc lcm*[T](x: openArray[T]): T {.since: (1, 1).} = while i < x.len: result = lcm(result, x[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 diff --git a/lib/pure/md5.nim b/lib/pure/md5.nim index 1ea71afd26db..ba944ba81311 100644 --- a/lib/pure/md5.nim +++ b/lib/pure/md5.nim @@ -278,12 +278,5 @@ proc md5Final*(c: var MD5Context, digest: var MD5Digest) = 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): {.pop.} #{.push styleChecks: off.} diff --git a/lib/pure/options.nim b/lib/pure/options.nim index 076cf37077b8..8de4430c1d5c 100644 --- a/lib/pure/options.nim +++ b/lib/pure/options.nim @@ -371,144 +371,3 @@ proc unsafeGet*[T](self: Option[T]): lent T {.inline.}= ## Generally, using `get proc <#get,Option[T]>`_ is preferred. assert self.isSome 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 diff --git a/lib/pure/parsecsv.nim b/lib/pure/parsecsv.nim index 2c0dbb802006..4a7117dc5bd0 100644 --- a/lib/pure/parsecsv.nim +++ b/lib/pure/parsecsv.nim @@ -357,35 +357,3 @@ when not defined(testing) and isMainModule: for val in items(x.row): echo "##", val, "##" 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") diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim index 4b123117ae04..29159816d918 100644 --- a/lib/pure/parseutils.nim +++ b/lib/pure/parseutils.nim @@ -651,47 +651,4 @@ iterator interpolatedFragments*(s: string): tuple[kind: InterpolatedKind, break 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.} diff --git a/lib/pure/punycode.nim b/lib/pure/punycode.nim index fc80fabfded1..e9e11a1c31bc 100644 --- a/lib/pure/punycode.nim +++ b/lib/pure/punycode.nim @@ -206,9 +206,3 @@ runnableExamples: doAssert decode("Mnchen-3ya-") == "Mnchen-3ya" doAssert decode("Mnchen-Ost-9db") == "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" diff --git a/lib/pure/random.nim b/lib/pure/random.nim index 3d9948d08e71..683140cd8dcf 100644 --- a/lib/pure/random.nim +++ b/lib/pure/random.nim @@ -651,57 +651,3 @@ when not defined(nimscript) and not defined(standalone): randomize(convert(Seconds, Nanoseconds, now.toUnix) + now.nanosecond) {.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() diff --git a/lib/pure/rationals.nim b/lib/pure/rationals.nim index c7af91eddc07..38a88ebc3a79 100644 --- a/lib/pure/rationals.nim +++ b/lib/pure/rationals.nim @@ -279,100 +279,3 @@ proc hash*[T](x: Rational[T]): Hash = h = h !& hash(copy.num) h = h !& hash(copy.den) 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 diff --git a/lib/pure/stats.nim b/lib/pure/stats.nim index 8684cb60a615..20fd1fdcd61f 100644 --- a/lib/pure/stats.nim +++ b/lib/pure/stats.nim @@ -335,50 +335,3 @@ runnableExamples: doAssert statistics.skewnessS() === 1.018350154434631 doAssert statistics.kurtosis() === -1.0 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())) diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index dc00271a5d02..de3f41f09cdd 100644 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -1520,17 +1520,3 @@ when false: var handle = open(filename, flags) if handle < 0: raise newEOS("posix.open() call failed") 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 diff --git a/lib/pure/strformat.nim b/lib/pure/strformat.nim index c37b6b1c050e..ddf996e4846f 100644 --- a/lib/pure/strformat.nim +++ b/lib/pure/strformat.nim @@ -660,145 +660,3 @@ macro fmt*(pattern: string; openChar, closeChar: char): untyped = doAssert """(()"foo" & "bar"())""".fmt(')', '(') == "(foobar)" doAssert """ ""{"123+123"}"" """.fmt('"', '"') == " \"{246}\" " 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") diff --git a/lib/pure/strmisc.nim b/lib/pure/strmisc.nim index 061c2063b675..5060deb78d0e 100644 --- a/lib/pure/strmisc.nim +++ b/lib/pure/strmisc.nim @@ -84,24 +84,3 @@ proc rpartition*(s: string, sep: string): (string, string, string) doAssert rpartition("foofoobar", "bar") == ("foofoo", "bar", "") 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", "") diff --git a/lib/pure/strscans.nim b/lib/pure/strscans.nim index f078b0d207c5..f7032f428fba 100644 --- a/lib/pure/strscans.nim +++ b/lib/pure/strscans.nim @@ -633,115 +633,3 @@ macro scanp*(input, idx: typed; pattern: varargs[untyped]): bool = result.add res when defined(debugScanp): 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 diff --git a/lib/pure/strtabs.nim b/lib/pure/strtabs.nim index 7b726e134059..7cf668d192a5 100644 --- a/lib/pure/strtabs.nim +++ b/lib/pure/strtabs.nim @@ -420,15 +420,3 @@ proc `%`*(f: string, t: StringTableRef, flags: set[FormatFlag] = {}): string {. else: add(result, f[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" diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 0eff80863ac4..f0b447de7938 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -2920,220 +2920,3 @@ proc isEmptyOrWhitespace*(s: string): bool {.noSideEffect, rtl, extern: "nsuIsEmptyOrWhitespace".} = ## Checks if `s` is empty or consists entirely of whitespace characters. 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() diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim index 8839a7767193..a28e98cafb39 100644 --- a/lib/pure/unicode.nim +++ b/lib/pure/unicode.nim @@ -1169,219 +1169,3 @@ proc alignLeft*(s: string, count: Natural, padding = ' '.Rune): string {. result.add padStr else: 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" diff --git a/lib/pure/unidecode/unidecode.nim b/lib/pure/unidecode/unidecode.nim index 30aaa7cd87f1..9a10ccc0073a 100644 --- a/lib/pure/unidecode/unidecode.nim +++ b/lib/pure/unidecode/unidecode.nim @@ -66,8 +66,3 @@ proc unidecode*(s: string): string = var c = int(r) if c <=% 127: add(result, chr(c)) 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 " diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim index 3e107a6b85ca..15d0996a78cb 100644 --- a/lib/pure/uri.nim +++ b/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" 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) - - -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!") diff --git a/lib/std/enumerate.nim b/lib/std/enumerate.nim index 3def653c83f1..a8f0e1ba7f8b 100644 --- a/lib/std/enumerate.nim +++ b/lib/std/enumerate.nim @@ -68,22 +68,3 @@ macro enumerate*(x: ForLoopStmt): untyped {.since: (1, 3).} = result.add newFor # now wrap the whole macro in a block to create a new scope 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)] diff --git a/lib/std/monotimes.nim b/lib/std/monotimes.nim index f819cbc8d186..c56bf77b30c6 100644 --- a/lib/std/monotimes.nim +++ b/lib/std/monotimes.nim @@ -152,19 +152,3 @@ proc high*(typ: typedesc[MonoTime]): MonoTime = proc low*(typ: typedesc[MonoTime]): MonoTime = ## Returns the lowest representable `MonoTime`. 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 diff --git a/lib/std/sha1.nim b/lib/std/sha1.nim index 9763b286e5f6..3c1674bcbe33 100644 --- a/lib/std/sha1.nim +++ b/lib/std/sha1.nim @@ -267,16 +267,3 @@ proc `==`*(a, b: SecureHash): bool = assert a == c # Not a constant-time comparison, but that's acceptable in this context 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") diff --git a/tests/stdlib/talgorithm.nim b/tests/stdlib/talgorithm.nim index 85ae792196d0..59336e70d5b3 100644 --- a/tests/stdlib/talgorithm.nim +++ b/tests/stdlib/talgorithm.nim @@ -16,3 +16,100 @@ proc test() = discard 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 diff --git a/tests/stdlib/tcookies.nim b/tests/stdlib/tcookies.nim new file mode 100644 index 000000000000..95b431b19aec --- /dev/null +++ b/tests/stdlib/tcookies.nim @@ -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" diff --git a/tests/stdlib/tcritbits.nim b/tests/stdlib/tcritbits.nim new file mode 100644 index 000000000000..51cbb7bf21ef --- /dev/null +++ b/tests/stdlib/tcritbits.nim @@ -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" diff --git a/tests/stdlib/tenumerate.nim b/tests/stdlib/tenumerate.nim new file mode 100644 index 000000000000..e5f21bc15b6f --- /dev/null +++ b/tests/stdlib/tenumerate.nim @@ -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)] diff --git a/tests/stdlib/tfenv.nim b/tests/stdlib/tfenv.nim new file mode 100644 index 000000000000..f58acf1c8d68 --- /dev/null +++ b/tests/stdlib/tfenv.nim @@ -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) diff --git a/tests/stdlib/thashes.nim b/tests/stdlib/thashes.nim index 259ced2aada6..d155111ffc8a 100644 --- a/tests/stdlib/thashes.nim +++ b/tests/stdlib/thashes.nim @@ -1,34 +1,71 @@ +import hashes -discard """ -output: ''' -[Suite] hashes +block hashes: + block hashing: + 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": - suite "hashing": - test "0.0 and -0.0 should have the same hash value": - var dummy = 0.0 - check hash(dummy) == hash(-dummy) + # "hashWangYi1 value incorrect at 456" + block: + when Hash.sizeof < 8: + doAssert hashWangYi1(456) == 1293320666 + else: + doAssert hashWangYi1(456) == -6421749900419628582 - test "VM and runtime should make the same hash value (hashIdentity)": - const hi123 = hashIdentity(123) - check hashIdentity(123) == hi123 +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 - test "VM and runtime should make the same hash value (hashWangYi1)": - const wy123 = hashWangYi1(123) - check hashWangYi1(123) == wy123 +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") - test "hashIdentity value incorrect at 456": - check hashIdentity(456) == 456 +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) - test "hashWangYi1 value incorrect at 456": - when Hash.sizeof < 8: - check hashWangYi1(456) == 1293320666 - else: - check hashWangYi1(456) == -6421749900419628582 +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) diff --git a/tests/stdlib/thttpcore.nim b/tests/stdlib/thttpcore.nim index cb1a0875fb86..fd5e1d90c80e 100644 --- a/tests/stdlib/thttpcore.nim +++ b/tests/stdlib/thttpcore.nim @@ -1,19 +1,12 @@ -discard """ -output: "[Suite] httpcore" -""" - -import unittest - import httpcore, strutils -suite "httpcore": - - test "HttpCode": +block: + block HttpCode: assert $Http418 == "418 I'm a teapot" assert Http418.is4xx() == true assert Http418.is2xx() == false - test "headers": + block headers: var h = newHttpHeaders() assert h.len == 0 h.add("Cookie", "foo") @@ -35,7 +28,7 @@ suite "httpcore": 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, prologue") == ("cookie", @["foo, bar, prologue"]) 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, starlight") == (key: "Accept", value: @["foo", "bar", "prologue", "starlight"]) - test "add empty sequence to HTTP headers": + block add_empty_sequence_to_HTTP_headers: block: var headers = newHttpHeaders() headers["empty"] = @[] @@ -78,3 +71,28 @@ suite "httpcore": headers["existing"] = @[] headers["existing"] = @["true"] 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" diff --git a/tests/stdlib/tmath.nim b/tests/stdlib/tmath.nim index 0de09a858398..ff1f32d364ff 100644 --- a/tests/stdlib/tmath.nim +++ b/tests/stdlib/tmath.nim @@ -145,3 +145,129 @@ suite "^": check: compiles(5.5 ^ 2.uint) check: compiles(5.5 ^ 2.uint8) 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 diff --git a/tests/stdlib/tmd5.nim b/tests/stdlib/tmd5.nim new file mode 100644 index 000000000000..736fa05a7631 --- /dev/null +++ b/tests/stdlib/tmd5.nim @@ -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") diff --git a/tests/stdlib/tmonotimes.nim b/tests/stdlib/tmonotimes.nim new file mode 100644 index 000000000000..cf25ef025851 --- /dev/null +++ b/tests/stdlib/tmonotimes.nim @@ -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 diff --git a/tests/stdlib/toptions.nim b/tests/stdlib/toptions.nim index b982d747d5fd..04544ffb77c3 100644 --- a/tests/stdlib/toptions.nim +++ b/tests/stdlib/toptions.nim @@ -13,4 +13,146 @@ type let js = """{"foo": {"test": "123"}}""" let parsed = parseJson(js) let a = parsed.to(Test) -echo $(%*a) \ No newline at end of file +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 diff --git a/tests/stdlib/tparsecsv.nim b/tests/stdlib/tparsecsv.nim new file mode 100644 index 000000000000..0d004d45d0bb --- /dev/null +++ b/tests/stdlib/tparsecsv.nim @@ -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") diff --git a/tests/stdlib/tparseutils.nim b/tests/stdlib/tparseutils.nim new file mode 100644 index 000000000000..3bc54dff193a --- /dev/null +++ b/tests/stdlib/tparseutils.nim @@ -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 diff --git a/tests/stdlib/tpunycode.nim b/tests/stdlib/tpunycode.nim new file mode 100644 index 000000000000..998bd3bdfabf --- /dev/null +++ b/tests/stdlib/tpunycode.nim @@ -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" diff --git a/tests/stdlib/trandom.nim b/tests/stdlib/trandom.nim new file mode 100644 index 000000000000..c7c6a3f56937 --- /dev/null +++ b/tests/stdlib/trandom.nim @@ -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() diff --git a/tests/stdlib/trationals.nim b/tests/stdlib/trationals.nim new file mode 100644 index 000000000000..17238af07476 --- /dev/null +++ b/tests/stdlib/trationals.nim @@ -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 diff --git a/tests/stdlib/tsha1.nim b/tests/stdlib/tsha1.nim new file mode 100644 index 000000000000..7e67ccaf61d2 --- /dev/null +++ b/tests/stdlib/tsha1.nim @@ -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") diff --git a/tests/stdlib/tstats.nim b/tests/stdlib/tstats.nim new file mode 100644 index 000000000000..37240c8848ff --- /dev/null +++ b/tests/stdlib/tstats.nim @@ -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())) \ No newline at end of file diff --git a/tests/stdlib/tstreams.nim b/tests/stdlib/tstreams.nim index 0fe6b69335fa..e0310b5f524d 100644 --- a/tests/stdlib/tstreams.nim +++ b/tests/stdlib/tstreams.nim @@ -61,3 +61,17 @@ doAssert a.readDataStr(buffer, 1..3) == 3 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 diff --git a/tests/stdlib/tstrformat.nim b/tests/stdlib/tstrformat.nim index b1f3340a4e1f..d483093a7653 100644 --- a/tests/stdlib/tstrformat.nim +++ b/tests/stdlib/tstrformat.nim @@ -6,7 +6,7 @@ output: '''Received (name: "Foo", species: "Bar")''' # issue #7632 import genericstrformat -import strutils +import strutils, times 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" + +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" \ No newline at end of file diff --git a/tests/stdlib/tstrmiscs.nim b/tests/stdlib/tstrmiscs.nim new file mode 100644 index 000000000000..2e9131ff807c --- /dev/null +++ b/tests/stdlib/tstrmiscs.nim @@ -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", "") diff --git a/tests/stdlib/tstrscans.nim b/tests/stdlib/tstrscans.nim index 6f952368c9a5..9d6f51025d6e 100644 --- a/tests/stdlib/tstrscans.nim +++ b/tests/stdlib/tstrscans.nim @@ -98,3 +98,115 @@ block issue15064: doAssert scanf(" ", "<$+> $*", nick3, msg3) doAssert nick3 == "abcd" 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 diff --git a/tests/stdlib/tstrtabs.nim b/tests/stdlib/tstrtabs.nim index 5d7e8c762cf9..d4344f95fc88 100644 --- a/tests/stdlib/tstrtabs.nim +++ b/tests/stdlib/tstrtabs.nim @@ -102,3 +102,15 @@ writeLine(stdout, "length of table ", $tab.len) writeLine(stdout, `%`("$key1 = $key2", tab, {useEnvironment})) tab.clear 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" diff --git a/tests/stdlib/tstrutil.nim b/tests/stdlib/tstrutil.nim index 162b8ea1b027..149d9bb87d36 100644 --- a/tests/stdlib/tstrutil.nim +++ b/tests/stdlib/tstrutil.nim @@ -457,3 +457,220 @@ hey assert 0 == indentation "" assert 0 == indentation " \n \n" 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() \ No newline at end of file diff --git a/tests/stdlib/ttables.nim b/tests/stdlib/ttables.nim new file mode 100644 index 000000000000..656d7be6bc40 --- /dev/null +++ b/tests/stdlib/ttables.nim @@ -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 diff --git a/tests/stdlib/tunicode.nim b/tests/stdlib/tunicode.nim new file mode 100644 index 000000000000..a346106f9ff3 --- /dev/null +++ b/tests/stdlib/tunicode.nim @@ -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" diff --git a/tests/stdlib/tunidecode.nim b/tests/stdlib/tunidecode.nim index 576bfa2cb123..7784fffb4635 100644 --- a/tests/stdlib/tunidecode.nim +++ b/tests/stdlib/tunidecode.nim @@ -9,6 +9,5 @@ import std/unidecode # #14112 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") - diff --git a/tests/stdlib/turi.nim b/tests/stdlib/turi.nim index 9fb349e88bc3..62fb17e4d40b 100644 --- a/tests/stdlib/turi.nim +++ b/tests/stdlib/turi.nim @@ -6,7 +6,7 @@ discard """ exitcode: 0 timeout: 60.0 """ -import uri +include uri block: @@ -15,3 +15,286 @@ block: doAssert url.hostname == "2001:0db8:85a3:0000:0000:8a2e:0370:7334" # true let newUrl = parseUri($url) 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")