improve tstrutils: test c, cpp, js, vm; cleanups (#16357)
* renamed: tests/stdlib/tstrutil.nim -> tests/stdlib/tstrutils.nim * improve test * enable tstrutils for js, vm
This commit is contained in:
parent
1082d62b08
commit
9ede956662
2 changed files with 689 additions and 676 deletions
|
|
@ -1,676 +0,0 @@
|
||||||
# test the new strutils module
|
|
||||||
|
|
||||||
import
|
|
||||||
strutils
|
|
||||||
|
|
||||||
template rejectParse(e) =
|
|
||||||
try:
|
|
||||||
discard e
|
|
||||||
raise newException(AssertionDefect, "This was supposed to fail: $#!" % astToStr(e))
|
|
||||||
except ValueError: discard
|
|
||||||
|
|
||||||
proc testStrip() =
|
|
||||||
doAssert strip(" ha ") == "ha"
|
|
||||||
|
|
||||||
proc testRemoveSuffix =
|
|
||||||
var s = "hello\n\r"
|
|
||||||
s.removeSuffix
|
|
||||||
assert s == "hello"
|
|
||||||
s.removeSuffix
|
|
||||||
assert s == "hello"
|
|
||||||
|
|
||||||
s = "hello\n\n"
|
|
||||||
s.removeSuffix
|
|
||||||
assert s == "hello"
|
|
||||||
|
|
||||||
s = "hello\r"
|
|
||||||
s.removeSuffix
|
|
||||||
assert s == "hello"
|
|
||||||
|
|
||||||
s = "hello \n there"
|
|
||||||
s.removeSuffix
|
|
||||||
assert s == "hello \n there"
|
|
||||||
|
|
||||||
s = "hello"
|
|
||||||
s.removeSuffix("llo")
|
|
||||||
assert s == "he"
|
|
||||||
s.removeSuffix('e')
|
|
||||||
assert s == "h"
|
|
||||||
|
|
||||||
s = "hellos"
|
|
||||||
s.removeSuffix({'s','z'})
|
|
||||||
assert s == "hello"
|
|
||||||
s.removeSuffix({'l','o'})
|
|
||||||
assert s == "he"
|
|
||||||
|
|
||||||
s = "aeiou"
|
|
||||||
s.removeSuffix("")
|
|
||||||
assert s == "aeiou"
|
|
||||||
|
|
||||||
s = ""
|
|
||||||
s.removeSuffix("")
|
|
||||||
assert s == ""
|
|
||||||
|
|
||||||
s = " "
|
|
||||||
s.removeSuffix
|
|
||||||
assert s == " "
|
|
||||||
|
|
||||||
s = " "
|
|
||||||
s.removeSuffix("")
|
|
||||||
assert s == " "
|
|
||||||
|
|
||||||
s = " "
|
|
||||||
s.removeSuffix(" ")
|
|
||||||
assert s == " "
|
|
||||||
|
|
||||||
s = " "
|
|
||||||
s.removeSuffix(' ')
|
|
||||||
assert s == ""
|
|
||||||
|
|
||||||
# Contrary to Chomp in other languages
|
|
||||||
# empty string does not change behaviour
|
|
||||||
s = "hello\r\n\r\n"
|
|
||||||
s.removeSuffix("")
|
|
||||||
assert s == "hello\r\n\r\n"
|
|
||||||
|
|
||||||
proc testRemovePrefix =
|
|
||||||
var s = "\n\rhello"
|
|
||||||
s.removePrefix
|
|
||||||
assert s == "hello"
|
|
||||||
s.removePrefix
|
|
||||||
assert s == "hello"
|
|
||||||
|
|
||||||
s = "\n\nhello"
|
|
||||||
s.removePrefix
|
|
||||||
assert s == "hello"
|
|
||||||
|
|
||||||
s = "\rhello"
|
|
||||||
s.removePrefix
|
|
||||||
assert s == "hello"
|
|
||||||
|
|
||||||
s = "hello \n there"
|
|
||||||
s.removePrefix
|
|
||||||
assert s == "hello \n there"
|
|
||||||
|
|
||||||
s = "hello"
|
|
||||||
s.removePrefix("hel")
|
|
||||||
assert s == "lo"
|
|
||||||
s.removePrefix('l')
|
|
||||||
assert s == "o"
|
|
||||||
|
|
||||||
s = "hellos"
|
|
||||||
s.removePrefix({'h','e'})
|
|
||||||
assert s == "llos"
|
|
||||||
s.removePrefix({'l','o'})
|
|
||||||
assert s == "s"
|
|
||||||
|
|
||||||
s = "aeiou"
|
|
||||||
s.removePrefix("")
|
|
||||||
assert s == "aeiou"
|
|
||||||
|
|
||||||
s = ""
|
|
||||||
s.removePrefix("")
|
|
||||||
assert s == ""
|
|
||||||
|
|
||||||
s = " "
|
|
||||||
s.removePrefix
|
|
||||||
assert s == " "
|
|
||||||
|
|
||||||
s = " "
|
|
||||||
s.removePrefix("")
|
|
||||||
assert s == " "
|
|
||||||
|
|
||||||
s = " "
|
|
||||||
s.removePrefix(" ")
|
|
||||||
assert s == " "
|
|
||||||
|
|
||||||
s = " "
|
|
||||||
s.removePrefix(' ')
|
|
||||||
assert s == ""
|
|
||||||
|
|
||||||
# Contrary to Chomp in other languages
|
|
||||||
# empty string does not change behaviour
|
|
||||||
s = "\r\n\r\nhello"
|
|
||||||
s.removePrefix("")
|
|
||||||
assert s == "\r\n\r\nhello"
|
|
||||||
|
|
||||||
proc main() =
|
|
||||||
testStrip()
|
|
||||||
testRemoveSuffix()
|
|
||||||
testRemovePrefix()
|
|
||||||
var ret: seq[string] # or use `toSeq`
|
|
||||||
for p in split("/home/a1:xyz:/usr/bin", {':'}): ret.add p
|
|
||||||
doAssert ret == @["/home/a1", "xyz", "/usr/bin"]
|
|
||||||
|
|
||||||
proc testDelete =
|
|
||||||
var s = "0123456789ABCDEFGH"
|
|
||||||
delete(s, 4, 5)
|
|
||||||
assert s == "01236789ABCDEFGH"
|
|
||||||
delete(s, s.len-1, s.len-1)
|
|
||||||
assert s == "01236789ABCDEFG"
|
|
||||||
delete(s, 0, 0)
|
|
||||||
assert s == "1236789ABCDEFG"
|
|
||||||
|
|
||||||
proc testFind =
|
|
||||||
assert "0123456789ABCDEFGH".find('A') == 10
|
|
||||||
assert "0123456789ABCDEFGH".find('A', 5) == 10
|
|
||||||
assert "0123456789ABCDEFGH".find('A', 5, 10) == 10
|
|
||||||
assert "0123456789ABCDEFGH".find('A', 5, 9) == -1
|
|
||||||
assert "0123456789ABCDEFGH".find("A") == 10
|
|
||||||
assert "0123456789ABCDEFGH".find("A", 5) == 10
|
|
||||||
assert "0123456789ABCDEFGH".find("A", 5, 10) == 10
|
|
||||||
assert "0123456789ABCDEFGH".find("A", 5, 9) == -1
|
|
||||||
assert "0123456789ABCDEFGH".find({'A'..'C'}) == 10
|
|
||||||
assert "0123456789ABCDEFGH".find({'A'..'C'}, 5) == 10
|
|
||||||
assert "0123456789ABCDEFGH".find({'A'..'C'}, 5, 10) == 10
|
|
||||||
assert "0123456789ABCDEFGH".find({'A'..'C'}, 5, 9) == -1
|
|
||||||
|
|
||||||
proc testRFind =
|
|
||||||
assert "0123456789ABCDEFGAH".rfind('A') == 17
|
|
||||||
assert "0123456789ABCDEFGAH".rfind('A', last=13) == 10
|
|
||||||
assert "0123456789ABCDEFGAH".rfind('H', last=13) == -1
|
|
||||||
assert "0123456789ABCDEFGAH".rfind("A") == 17
|
|
||||||
assert "0123456789ABCDEFGAH".rfind("A", last=13) == 10
|
|
||||||
assert "0123456789ABCDEFGAH".rfind("H", last=13) == -1
|
|
||||||
assert "0123456789ABCDEFGAH".rfind({'A'..'C'}) == 17
|
|
||||||
assert "0123456789ABCDEFGAH".rfind({'A'..'C'}, last=13) == 12
|
|
||||||
assert "0123456789ABCDEFGAH".rfind({'G'..'H'}, last=13) == -1
|
|
||||||
assert "0123456789ABCDEFGAH".rfind('A', start=18) == -1
|
|
||||||
assert "0123456789ABCDEFGAH".rfind('A', start=11, last=17) == 17
|
|
||||||
assert "0123456789ABCDEFGAH".rfind("0", start=0) == 0
|
|
||||||
assert "0123456789ABCDEFGAH".rfind("0", start=1) == -1
|
|
||||||
assert "0123456789ABCDEFGAH".rfind("H", start=11) == 18
|
|
||||||
assert "0123456789ABCDEFGAH".rfind({'0'..'9'}, start=5) == 9
|
|
||||||
assert "0123456789ABCDEFGAH".rfind({'0'..'9'}, start=10) == -1
|
|
||||||
|
|
||||||
proc testTrimZeros() =
|
|
||||||
var x = "1200"
|
|
||||||
x.trimZeros()
|
|
||||||
assert x == "1200"
|
|
||||||
x = "120.0"
|
|
||||||
x.trimZeros()
|
|
||||||
assert x == "120"
|
|
||||||
x = "0."
|
|
||||||
x.trimZeros()
|
|
||||||
assert x == "0"
|
|
||||||
x = "1.0e2"
|
|
||||||
x.trimZeros()
|
|
||||||
assert x == "1e2"
|
|
||||||
x = "78.90"
|
|
||||||
x.trimZeros()
|
|
||||||
assert x == "78.9"
|
|
||||||
x = "1.23e4"
|
|
||||||
x.trimZeros()
|
|
||||||
assert x == "1.23e4"
|
|
||||||
x = "1.01"
|
|
||||||
x.trimZeros()
|
|
||||||
assert x == "1.01"
|
|
||||||
x = "1.1001"
|
|
||||||
x.trimZeros()
|
|
||||||
assert x == "1.1001"
|
|
||||||
x = "0.0"
|
|
||||||
x.trimZeros()
|
|
||||||
assert x == "0"
|
|
||||||
x = "0.01"
|
|
||||||
x.trimZeros()
|
|
||||||
assert x == "0.01"
|
|
||||||
x = "1e0"
|
|
||||||
x.trimZeros()
|
|
||||||
assert x == "1e0"
|
|
||||||
|
|
||||||
proc testSplitLines() =
|
|
||||||
let fixture = "a\nb\rc\r\nd"
|
|
||||||
assert len(fixture.splitLines) == 4
|
|
||||||
assert splitLines(fixture) == @["a", "b", "c", "d"]
|
|
||||||
assert splitLines(fixture, keepEol=true) == @["a\n", "b\r", "c\r\n", "d"]
|
|
||||||
|
|
||||||
proc testCountLines =
|
|
||||||
proc assertCountLines(s: string) = assert s.countLines == s.splitLines.len
|
|
||||||
assertCountLines("")
|
|
||||||
assertCountLines("\n")
|
|
||||||
assertCountLines("\n\n")
|
|
||||||
assertCountLines("abc")
|
|
||||||
assertCountLines("abc\n123")
|
|
||||||
assertCountLines("abc\n123\n")
|
|
||||||
assertCountLines("\nabc\n123")
|
|
||||||
assertCountLines("\nabc\n123\n")
|
|
||||||
|
|
||||||
proc testParseInts =
|
|
||||||
# binary
|
|
||||||
assert "0b1111".parseBinInt == 15
|
|
||||||
assert "0B1111".parseBinInt == 15
|
|
||||||
assert "1111".parseBinInt == 15
|
|
||||||
assert "1110".parseBinInt == 14
|
|
||||||
assert "1_1_1_1".parseBinInt == 15
|
|
||||||
assert "0b1_1_1_1".parseBinInt == 15
|
|
||||||
rejectParse "".parseBinInt
|
|
||||||
rejectParse "_".parseBinInt
|
|
||||||
rejectParse "0b".parseBinInt
|
|
||||||
rejectParse "0b1234".parseBinInt
|
|
||||||
# hex
|
|
||||||
assert "0x72".parseHexInt == 114
|
|
||||||
assert "0X72".parseHexInt == 114
|
|
||||||
assert "#72".parseHexInt == 114
|
|
||||||
assert "72".parseHexInt == 114
|
|
||||||
assert "FF".parseHexInt == 255
|
|
||||||
assert "ff".parseHexInt == 255
|
|
||||||
assert "fF".parseHexInt == 255
|
|
||||||
assert "0x7_2".parseHexInt == 114
|
|
||||||
rejectParse "".parseHexInt
|
|
||||||
rejectParse "_".parseHexInt
|
|
||||||
rejectParse "0x".parseHexInt
|
|
||||||
rejectParse "0xFFG".parseHexInt
|
|
||||||
rejectParse "reject".parseHexInt
|
|
||||||
# octal
|
|
||||||
assert "0o17".parseOctInt == 15
|
|
||||||
assert "0O17".parseOctInt == 15
|
|
||||||
assert "17".parseOctInt == 15
|
|
||||||
assert "10".parseOctInt == 8
|
|
||||||
assert "0o1_0_0".parseOctInt == 64
|
|
||||||
rejectParse "".parseOctInt
|
|
||||||
rejectParse "_".parseOctInt
|
|
||||||
rejectParse "0o".parseOctInt
|
|
||||||
rejectParse "9".parseOctInt
|
|
||||||
rejectParse "0o9".parseOctInt
|
|
||||||
rejectParse "reject".parseOctInt
|
|
||||||
|
|
||||||
testDelete()
|
|
||||||
testFind()
|
|
||||||
testRFind()
|
|
||||||
testTrimZeros()
|
|
||||||
testSplitLines()
|
|
||||||
testCountLines()
|
|
||||||
testParseInts()
|
|
||||||
|
|
||||||
assert(insertSep($1000_000) == "1_000_000")
|
|
||||||
assert(insertSep($232) == "232")
|
|
||||||
assert(insertSep($12345, ',') == "12,345")
|
|
||||||
assert(insertSep($0) == "0")
|
|
||||||
|
|
||||||
assert "/1/2/3".rfind('/') == 4
|
|
||||||
assert "/1/2/3".rfind('/', last=1) == 0
|
|
||||||
assert "/1/2/3".rfind('0') == -1
|
|
||||||
|
|
||||||
assert(toHex(100i16, 32) == "00000000000000000000000000000064")
|
|
||||||
assert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C")
|
|
||||||
|
|
||||||
assert(toHex(high(uint64)) == "FFFFFFFFFFFFFFFF")
|
|
||||||
assert(toHex(high(uint64), 16) == "FFFFFFFFFFFFFFFF")
|
|
||||||
assert(toHex(high(uint64), 32) == "0000000000000000FFFFFFFFFFFFFFFF")
|
|
||||||
|
|
||||||
assert "".parseHexStr == ""
|
|
||||||
assert "00Ff80".parseHexStr == "\0\xFF\x80"
|
|
||||||
try:
|
|
||||||
discard "00Ff8".parseHexStr
|
|
||||||
assert false, "Should raise ValueError"
|
|
||||||
except ValueError:
|
|
||||||
discard
|
|
||||||
|
|
||||||
try:
|
|
||||||
discard "0k".parseHexStr
|
|
||||||
assert false, "Should raise ValueError"
|
|
||||||
except ValueError:
|
|
||||||
discard
|
|
||||||
|
|
||||||
assert "".toHex == ""
|
|
||||||
assert "\x00\xFF\x80".toHex == "00FF80"
|
|
||||||
assert "0123456789abcdef".parseHexStr.toHex == "0123456789ABCDEF"
|
|
||||||
|
|
||||||
assert(' '.repeat(8) == " ")
|
|
||||||
assert(" ".repeat(8) == " ")
|
|
||||||
assert(spaces(8) == " ")
|
|
||||||
|
|
||||||
assert(' '.repeat(0) == "")
|
|
||||||
assert(" ".repeat(0) == "")
|
|
||||||
assert(spaces(0) == "")
|
|
||||||
|
|
||||||
# bug #11369
|
|
||||||
|
|
||||||
var num: int64 = -1
|
|
||||||
assert num.toBin(64) == "1111111111111111111111111111111111111111111111111111111111111111"
|
|
||||||
assert num.toOct(24) == "001777777777777777777777"
|
|
||||||
|
|
||||||
|
|
||||||
# bug #8911
|
|
||||||
when true:
|
|
||||||
static:
|
|
||||||
let a = ""
|
|
||||||
let a2 = a.replace("\n", "\\n")
|
|
||||||
|
|
||||||
when true:
|
|
||||||
static:
|
|
||||||
let b = "b"
|
|
||||||
let b2 = b.replace("\n", "\\n")
|
|
||||||
|
|
||||||
when true:
|
|
||||||
let c = ""
|
|
||||||
let c2 = c.replace("\n", "\\n")
|
|
||||||
|
|
||||||
main()
|
|
||||||
#OUT ha/home/a1xyz/usr/bin
|
|
||||||
|
|
||||||
|
|
||||||
# `parseEnum`, ref issue #14030
|
|
||||||
# check enum defined at top level
|
|
||||||
type
|
|
||||||
Foo = enum
|
|
||||||
A = -10
|
|
||||||
B = "bb"
|
|
||||||
C = (-5, "ccc")
|
|
||||||
D = 15
|
|
||||||
E = "ee" # check that we count enum fields correctly
|
|
||||||
|
|
||||||
block:
|
|
||||||
let a = parseEnum[Foo]("A")
|
|
||||||
let b = parseEnum[Foo]("bb")
|
|
||||||
let c = parseEnum[Foo]("ccc")
|
|
||||||
let d = parseEnum[Foo]("D")
|
|
||||||
let e = parseEnum[Foo]("ee")
|
|
||||||
doAssert a == A
|
|
||||||
doAssert b == B
|
|
||||||
doAssert c == C
|
|
||||||
doAssert d == D
|
|
||||||
doAssert e == E
|
|
||||||
try:
|
|
||||||
let f = parseEnum[Foo]("Bar")
|
|
||||||
doAssert false
|
|
||||||
except ValueError:
|
|
||||||
discard
|
|
||||||
|
|
||||||
# finally using default
|
|
||||||
let g = parseEnum[Foo]("Bar", A)
|
|
||||||
doAssert g == A
|
|
||||||
|
|
||||||
block:
|
|
||||||
# check enum defined in block
|
|
||||||
type
|
|
||||||
Bar = enum
|
|
||||||
V
|
|
||||||
W = "ww"
|
|
||||||
X = (3, "xx")
|
|
||||||
Y = 10
|
|
||||||
Z = "zz" # check that we count enum fields correctly
|
|
||||||
|
|
||||||
let a = parseEnum[Bar]("V")
|
|
||||||
let b = parseEnum[Bar]("ww")
|
|
||||||
let c = parseEnum[Bar]("xx")
|
|
||||||
let d = parseEnum[Bar]("Y")
|
|
||||||
let e = parseEnum[Bar]("zz")
|
|
||||||
doAssert a == V
|
|
||||||
doAssert b == W
|
|
||||||
doAssert c == X
|
|
||||||
doAssert d == Y
|
|
||||||
doAssert e == Z
|
|
||||||
try:
|
|
||||||
let f = parseEnum[Bar]("Baz")
|
|
||||||
doAssert false
|
|
||||||
except ValueError:
|
|
||||||
discard
|
|
||||||
|
|
||||||
# finally using default
|
|
||||||
let g = parseEnum[Bar]("Baz", V)
|
|
||||||
doAssert g == V
|
|
||||||
|
|
||||||
block:
|
|
||||||
# check ambiguous enum fails to parse
|
|
||||||
type
|
|
||||||
Ambig = enum
|
|
||||||
f1 = "A"
|
|
||||||
f2 = "B"
|
|
||||||
f3 = "A"
|
|
||||||
|
|
||||||
doAssert not compiles((let a = parseEnum[Ambig]("A")))
|
|
||||||
|
|
||||||
block:
|
|
||||||
# check almost ambiguous enum
|
|
||||||
type
|
|
||||||
AlmostAmbig = enum
|
|
||||||
f1 = "someA"
|
|
||||||
f2 = "someB"
|
|
||||||
f3 = "SomeA"
|
|
||||||
|
|
||||||
let a = parseEnum[AlmostAmbig]("someA")
|
|
||||||
let b = parseEnum[AlmostAmbig]("someB")
|
|
||||||
let c = parseEnum[AlmostAmbig]("SomeA")
|
|
||||||
doAssert a == f1
|
|
||||||
doAssert b == f2
|
|
||||||
doAssert c == f3
|
|
||||||
|
|
||||||
block:
|
|
||||||
assert 0 == indentation """
|
|
||||||
hey
|
|
||||||
low
|
|
||||||
there
|
|
||||||
"""
|
|
||||||
assert 2 == indentation """
|
|
||||||
hey
|
|
||||||
low
|
|
||||||
there
|
|
||||||
"""
|
|
||||||
assert 2 == indentation """ hey
|
|
||||||
low
|
|
||||||
there
|
|
||||||
"""
|
|
||||||
assert 2 == indentation """ hey
|
|
||||||
low
|
|
||||||
there"""
|
|
||||||
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()
|
|
||||||
689
tests/stdlib/tstrutils.nim
Normal file
689
tests/stdlib/tstrutils.nim
Normal file
|
|
@ -0,0 +1,689 @@
|
||||||
|
discard """
|
||||||
|
targets: "c cpp js"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import std/strutils
|
||||||
|
|
||||||
|
# xxx each instance of `disableVm` and `when not defined js:` should eventually be fixed
|
||||||
|
|
||||||
|
template rejectParse(e) =
|
||||||
|
try:
|
||||||
|
discard e
|
||||||
|
raise newException(AssertionDefect, "This was supposed to fail: $#!" % astToStr(e))
|
||||||
|
except ValueError: discard
|
||||||
|
|
||||||
|
template disableVm(body) =
|
||||||
|
when nimvm: discard
|
||||||
|
else: body
|
||||||
|
|
||||||
|
template main() =
|
||||||
|
block: # strip
|
||||||
|
doAssert strip(" ha ") == "ha"
|
||||||
|
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"
|
||||||
|
|
||||||
|
block: # split
|
||||||
|
var ret: seq[string] # or use `toSeq` or `collect`
|
||||||
|
for p in split("/home/a1:xyz:/usr/bin", {':'}): ret.add p
|
||||||
|
doAssert ret == @["/home/a1", "xyz", "/usr/bin"]
|
||||||
|
|
||||||
|
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 "]
|
||||||
|
|
||||||
|
block: # splitLines
|
||||||
|
let fixture = "a\nb\rc\r\nd"
|
||||||
|
assert len(fixture.splitLines) == 4
|
||||||
|
assert splitLines(fixture) == @["a", "b", "c", "d"]
|
||||||
|
assert splitLines(fixture, keepEol=true) == @["a\n", "b\r", "c\r\n", "d"]
|
||||||
|
|
||||||
|
block: # rsplit
|
||||||
|
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"]
|
||||||
|
|
||||||
|
block: # splitWhitespace
|
||||||
|
let s = " 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: # removeSuffix
|
||||||
|
var s = "hello\n\r"
|
||||||
|
s.removeSuffix
|
||||||
|
assert s == "hello"
|
||||||
|
s.removeSuffix
|
||||||
|
assert s == "hello"
|
||||||
|
|
||||||
|
s = "hello\n\n"
|
||||||
|
s.removeSuffix
|
||||||
|
assert s == "hello"
|
||||||
|
|
||||||
|
s = "hello\r"
|
||||||
|
s.removeSuffix
|
||||||
|
assert s == "hello"
|
||||||
|
|
||||||
|
s = "hello \n there"
|
||||||
|
s.removeSuffix
|
||||||
|
assert s == "hello \n there"
|
||||||
|
|
||||||
|
s = "hello"
|
||||||
|
s.removeSuffix("llo")
|
||||||
|
assert s == "he"
|
||||||
|
s.removeSuffix('e')
|
||||||
|
assert s == "h"
|
||||||
|
|
||||||
|
s = "hellos"
|
||||||
|
s.removeSuffix({'s','z'})
|
||||||
|
assert s == "hello"
|
||||||
|
s.removeSuffix({'l','o'})
|
||||||
|
assert s == "he"
|
||||||
|
|
||||||
|
s = "aeiou"
|
||||||
|
s.removeSuffix("")
|
||||||
|
assert s == "aeiou"
|
||||||
|
|
||||||
|
s = ""
|
||||||
|
s.removeSuffix("")
|
||||||
|
assert s == ""
|
||||||
|
|
||||||
|
s = " "
|
||||||
|
s.removeSuffix
|
||||||
|
assert s == " "
|
||||||
|
|
||||||
|
s = " "
|
||||||
|
s.removeSuffix("")
|
||||||
|
assert s == " "
|
||||||
|
|
||||||
|
s = " "
|
||||||
|
s.removeSuffix(" ")
|
||||||
|
assert s == " "
|
||||||
|
|
||||||
|
s = " "
|
||||||
|
s.removeSuffix(' ')
|
||||||
|
assert s == ""
|
||||||
|
|
||||||
|
# Contrary to Chomp in other languages
|
||||||
|
# empty string does not change behaviour
|
||||||
|
s = "hello\r\n\r\n"
|
||||||
|
s.removeSuffix("")
|
||||||
|
assert s == "hello\r\n\r\n"
|
||||||
|
|
||||||
|
block: # removePrefix
|
||||||
|
var s = "\n\rhello"
|
||||||
|
s.removePrefix
|
||||||
|
assert s == "hello"
|
||||||
|
s.removePrefix
|
||||||
|
assert s == "hello"
|
||||||
|
|
||||||
|
s = "\n\nhello"
|
||||||
|
s.removePrefix
|
||||||
|
assert s == "hello"
|
||||||
|
|
||||||
|
s = "\rhello"
|
||||||
|
s.removePrefix
|
||||||
|
assert s == "hello"
|
||||||
|
|
||||||
|
s = "hello \n there"
|
||||||
|
s.removePrefix
|
||||||
|
assert s == "hello \n there"
|
||||||
|
|
||||||
|
s = "hello"
|
||||||
|
s.removePrefix("hel")
|
||||||
|
assert s == "lo"
|
||||||
|
s.removePrefix('l')
|
||||||
|
assert s == "o"
|
||||||
|
|
||||||
|
s = "hellos"
|
||||||
|
s.removePrefix({'h','e'})
|
||||||
|
assert s == "llos"
|
||||||
|
s.removePrefix({'l','o'})
|
||||||
|
assert s == "s"
|
||||||
|
|
||||||
|
s = "aeiou"
|
||||||
|
s.removePrefix("")
|
||||||
|
assert s == "aeiou"
|
||||||
|
|
||||||
|
s = ""
|
||||||
|
s.removePrefix("")
|
||||||
|
assert s == ""
|
||||||
|
|
||||||
|
s = " "
|
||||||
|
s.removePrefix
|
||||||
|
assert s == " "
|
||||||
|
|
||||||
|
s = " "
|
||||||
|
s.removePrefix("")
|
||||||
|
assert s == " "
|
||||||
|
|
||||||
|
s = " "
|
||||||
|
s.removePrefix(" ")
|
||||||
|
assert s == " "
|
||||||
|
|
||||||
|
s = " "
|
||||||
|
s.removePrefix(' ')
|
||||||
|
assert s == ""
|
||||||
|
|
||||||
|
# Contrary to Chomp in other languages
|
||||||
|
# empty string does not change behaviour
|
||||||
|
s = "\r\n\r\nhello"
|
||||||
|
s.removePrefix("")
|
||||||
|
assert s == "\r\n\r\nhello"
|
||||||
|
|
||||||
|
block: # delete
|
||||||
|
var s = "0123456789ABCDEFGH"
|
||||||
|
delete(s, 4, 5)
|
||||||
|
assert s == "01236789ABCDEFGH"
|
||||||
|
delete(s, s.len-1, s.len-1)
|
||||||
|
assert s == "01236789ABCDEFG"
|
||||||
|
delete(s, 0, 0)
|
||||||
|
assert s == "1236789ABCDEFG"
|
||||||
|
|
||||||
|
block: # find
|
||||||
|
assert "0123456789ABCDEFGH".find('A') == 10
|
||||||
|
assert "0123456789ABCDEFGH".find('A', 5) == 10
|
||||||
|
assert "0123456789ABCDEFGH".find('A', 5, 10) == 10
|
||||||
|
assert "0123456789ABCDEFGH".find('A', 5, 9) == -1
|
||||||
|
assert "0123456789ABCDEFGH".find("A") == 10
|
||||||
|
assert "0123456789ABCDEFGH".find("A", 5) == 10
|
||||||
|
assert "0123456789ABCDEFGH".find("A", 5, 10) == 10
|
||||||
|
assert "0123456789ABCDEFGH".find("A", 5, 9) == -1
|
||||||
|
assert "0123456789ABCDEFGH".find({'A'..'C'}) == 10
|
||||||
|
assert "0123456789ABCDEFGH".find({'A'..'C'}, 5) == 10
|
||||||
|
assert "0123456789ABCDEFGH".find({'A'..'C'}, 5, 10) == 10
|
||||||
|
assert "0123456789ABCDEFGH".find({'A'..'C'}, 5, 9) == -1
|
||||||
|
|
||||||
|
block: # rfind
|
||||||
|
assert "0123456789ABCDEFGAH".rfind('A') == 17
|
||||||
|
assert "0123456789ABCDEFGAH".rfind('A', last=13) == 10
|
||||||
|
assert "0123456789ABCDEFGAH".rfind('H', last=13) == -1
|
||||||
|
assert "0123456789ABCDEFGAH".rfind("A") == 17
|
||||||
|
assert "0123456789ABCDEFGAH".rfind("A", last=13) == 10
|
||||||
|
assert "0123456789ABCDEFGAH".rfind("H", last=13) == -1
|
||||||
|
assert "0123456789ABCDEFGAH".rfind({'A'..'C'}) == 17
|
||||||
|
assert "0123456789ABCDEFGAH".rfind({'A'..'C'}, last=13) == 12
|
||||||
|
assert "0123456789ABCDEFGAH".rfind({'G'..'H'}, last=13) == -1
|
||||||
|
assert "0123456789ABCDEFGAH".rfind('A', start=18) == -1
|
||||||
|
assert "0123456789ABCDEFGAH".rfind('A', start=11, last=17) == 17
|
||||||
|
assert "0123456789ABCDEFGAH".rfind("0", start=0) == 0
|
||||||
|
assert "0123456789ABCDEFGAH".rfind("0", start=1) == -1
|
||||||
|
assert "0123456789ABCDEFGAH".rfind("H", start=11) == 18
|
||||||
|
assert "0123456789ABCDEFGAH".rfind({'0'..'9'}, start=5) == 9
|
||||||
|
assert "0123456789ABCDEFGAH".rfind({'0'..'9'}, start=10) == -1
|
||||||
|
|
||||||
|
assert "/1/2/3".rfind('/') == 4
|
||||||
|
assert "/1/2/3".rfind('/', last=1) == 0
|
||||||
|
assert "/1/2/3".rfind('0') == -1
|
||||||
|
|
||||||
|
block: # trimZeros
|
||||||
|
var x = "1200"
|
||||||
|
x.trimZeros()
|
||||||
|
assert x == "1200"
|
||||||
|
x = "120.0"
|
||||||
|
x.trimZeros()
|
||||||
|
assert x == "120"
|
||||||
|
x = "0."
|
||||||
|
x.trimZeros()
|
||||||
|
assert x == "0"
|
||||||
|
x = "1.0e2"
|
||||||
|
x.trimZeros()
|
||||||
|
assert x == "1e2"
|
||||||
|
x = "78.90"
|
||||||
|
x.trimZeros()
|
||||||
|
assert x == "78.9"
|
||||||
|
x = "1.23e4"
|
||||||
|
x.trimZeros()
|
||||||
|
assert x == "1.23e4"
|
||||||
|
x = "1.01"
|
||||||
|
x.trimZeros()
|
||||||
|
assert x == "1.01"
|
||||||
|
x = "1.1001"
|
||||||
|
x.trimZeros()
|
||||||
|
assert x == "1.1001"
|
||||||
|
x = "0.0"
|
||||||
|
x.trimZeros()
|
||||||
|
assert x == "0"
|
||||||
|
x = "0.01"
|
||||||
|
x.trimZeros()
|
||||||
|
assert x == "0.01"
|
||||||
|
x = "1e0"
|
||||||
|
x.trimZeros()
|
||||||
|
assert x == "1e0"
|
||||||
|
|
||||||
|
block: # countLines
|
||||||
|
proc assertCountLines(s: string) = assert s.countLines == s.splitLines.len
|
||||||
|
assertCountLines("")
|
||||||
|
assertCountLines("\n")
|
||||||
|
assertCountLines("\n\n")
|
||||||
|
assertCountLines("abc")
|
||||||
|
assertCountLines("abc\n123")
|
||||||
|
assertCountLines("abc\n123\n")
|
||||||
|
assertCountLines("\nabc\n123")
|
||||||
|
assertCountLines("\nabc\n123\n")
|
||||||
|
|
||||||
|
block: # parseBinInt, parseHexInt, parseOctInt
|
||||||
|
# binary
|
||||||
|
assert "0b1111".parseBinInt == 15
|
||||||
|
assert "0B1111".parseBinInt == 15
|
||||||
|
assert "1111".parseBinInt == 15
|
||||||
|
assert "1110".parseBinInt == 14
|
||||||
|
assert "1_1_1_1".parseBinInt == 15
|
||||||
|
assert "0b1_1_1_1".parseBinInt == 15
|
||||||
|
rejectParse "".parseBinInt
|
||||||
|
rejectParse "_".parseBinInt
|
||||||
|
rejectParse "0b".parseBinInt
|
||||||
|
rejectParse "0b1234".parseBinInt
|
||||||
|
# hex
|
||||||
|
assert "0x72".parseHexInt == 114
|
||||||
|
assert "0X72".parseHexInt == 114
|
||||||
|
assert "#72".parseHexInt == 114
|
||||||
|
assert "72".parseHexInt == 114
|
||||||
|
assert "FF".parseHexInt == 255
|
||||||
|
assert "ff".parseHexInt == 255
|
||||||
|
assert "fF".parseHexInt == 255
|
||||||
|
assert "0x7_2".parseHexInt == 114
|
||||||
|
rejectParse "".parseHexInt
|
||||||
|
rejectParse "_".parseHexInt
|
||||||
|
rejectParse "0x".parseHexInt
|
||||||
|
rejectParse "0xFFG".parseHexInt
|
||||||
|
rejectParse "reject".parseHexInt
|
||||||
|
# octal
|
||||||
|
assert "0o17".parseOctInt == 15
|
||||||
|
assert "0O17".parseOctInt == 15
|
||||||
|
assert "17".parseOctInt == 15
|
||||||
|
assert "10".parseOctInt == 8
|
||||||
|
assert "0o1_0_0".parseOctInt == 64
|
||||||
|
rejectParse "".parseOctInt
|
||||||
|
rejectParse "_".parseOctInt
|
||||||
|
rejectParse "0o".parseOctInt
|
||||||
|
rejectParse "9".parseOctInt
|
||||||
|
rejectParse "0o9".parseOctInt
|
||||||
|
rejectParse "reject".parseOctInt
|
||||||
|
|
||||||
|
block: # parseHexStr
|
||||||
|
assert "".parseHexStr == ""
|
||||||
|
assert "00Ff80".parseHexStr == "\0\xFF\x80"
|
||||||
|
try:
|
||||||
|
discard "00Ff8".parseHexStr
|
||||||
|
assert false, "Should raise ValueError"
|
||||||
|
except ValueError:
|
||||||
|
discard
|
||||||
|
|
||||||
|
try:
|
||||||
|
discard "0k".parseHexStr
|
||||||
|
assert false, "Should raise ValueError"
|
||||||
|
except ValueError:
|
||||||
|
discard
|
||||||
|
|
||||||
|
assert "".toHex == ""
|
||||||
|
assert "\x00\xFF\x80".toHex == "00FF80"
|
||||||
|
assert "0123456789abcdef".parseHexStr.toHex == "0123456789ABCDEF"
|
||||||
|
|
||||||
|
block: # toHex
|
||||||
|
assert(toHex(100i16, 32) == "00000000000000000000000000000064")
|
||||||
|
assert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C")
|
||||||
|
when not defined js:
|
||||||
|
assert(toHex(high(uint64)) == "FFFFFFFFFFFFFFFF")
|
||||||
|
assert(toHex(high(uint64), 16) == "FFFFFFFFFFFFFFFF")
|
||||||
|
assert(toHex(high(uint64), 32) == "0000000000000000FFFFFFFFFFFFFFFF")
|
||||||
|
|
||||||
|
block: # insertSep
|
||||||
|
assert(insertSep($1000_000) == "1_000_000")
|
||||||
|
assert(insertSep($232) == "232")
|
||||||
|
assert(insertSep($12345, ',') == "12,345")
|
||||||
|
assert(insertSep($0) == "0")
|
||||||
|
|
||||||
|
block: # repeat, spaces
|
||||||
|
assert(' '.repeat(8) == " ")
|
||||||
|
assert(" ".repeat(8) == " ")
|
||||||
|
assert(spaces(8) == " ")
|
||||||
|
|
||||||
|
assert(' '.repeat(0) == "")
|
||||||
|
assert(" ".repeat(0) == "")
|
||||||
|
assert(spaces(0) == "")
|
||||||
|
|
||||||
|
block: # toBin, toOct
|
||||||
|
block:# bug #11369
|
||||||
|
var num: int64 = -1
|
||||||
|
when not defined js:
|
||||||
|
assert num.toBin(64) == "1111111111111111111111111111111111111111111111111111111111111111"
|
||||||
|
assert num.toOct(24) == "001777777777777777777777"
|
||||||
|
|
||||||
|
block: # replace
|
||||||
|
doAssert "oo".replace("", "abc") == "oo"
|
||||||
|
# bug #8911
|
||||||
|
static:
|
||||||
|
let a = ""
|
||||||
|
let a2 = a.replace("\n", "\\n")
|
||||||
|
|
||||||
|
static:
|
||||||
|
let b = "b"
|
||||||
|
let b2 = b.replace("\n", "\\n")
|
||||||
|
|
||||||
|
block:
|
||||||
|
let c = ""
|
||||||
|
let c2 = c.replace("\n", "\\n")
|
||||||
|
|
||||||
|
block: # replaceWord
|
||||||
|
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"
|
||||||
|
|
||||||
|
block: # multiReplace
|
||||||
|
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"
|
||||||
|
|
||||||
|
# `parseEnum`, ref issue #14030
|
||||||
|
# check enum defined at top level # xxx this is probably irrelevant, and pollutes scope
|
||||||
|
# for remaining tests
|
||||||
|
type
|
||||||
|
Foo = enum
|
||||||
|
A = -10
|
||||||
|
B = "bb"
|
||||||
|
C = (-5, "ccc")
|
||||||
|
D = 15
|
||||||
|
E = "ee" # check that we count enum fields correctly
|
||||||
|
|
||||||
|
block: # parseEnum
|
||||||
|
block:
|
||||||
|
let a = parseEnum[Foo]("A")
|
||||||
|
let b = parseEnum[Foo]("bb")
|
||||||
|
let c = parseEnum[Foo]("ccc")
|
||||||
|
let d = parseEnum[Foo]("D")
|
||||||
|
let e = parseEnum[Foo]("ee")
|
||||||
|
doAssert a == A
|
||||||
|
doAssert b == B
|
||||||
|
doAssert c == C
|
||||||
|
doAssert d == D
|
||||||
|
doAssert e == E
|
||||||
|
try:
|
||||||
|
let f = parseEnum[Foo]("Bar")
|
||||||
|
doAssert false
|
||||||
|
except ValueError:
|
||||||
|
discard
|
||||||
|
|
||||||
|
# finally using default
|
||||||
|
let g = parseEnum[Foo]("Bar", A)
|
||||||
|
doAssert g == A
|
||||||
|
|
||||||
|
block: # check enum defined in block
|
||||||
|
type
|
||||||
|
Bar = enum
|
||||||
|
V
|
||||||
|
W = "ww"
|
||||||
|
X = (3, "xx")
|
||||||
|
Y = 10
|
||||||
|
Z = "zz" # check that we count enum fields correctly
|
||||||
|
|
||||||
|
let a = parseEnum[Bar]("V")
|
||||||
|
let b = parseEnum[Bar]("ww")
|
||||||
|
let c = parseEnum[Bar]("xx")
|
||||||
|
let d = parseEnum[Bar]("Y")
|
||||||
|
let e = parseEnum[Bar]("zz")
|
||||||
|
doAssert a == V
|
||||||
|
doAssert b == W
|
||||||
|
doAssert c == X
|
||||||
|
doAssert d == Y
|
||||||
|
doAssert e == Z
|
||||||
|
try:
|
||||||
|
let f = parseEnum[Bar]("Baz")
|
||||||
|
doAssert false
|
||||||
|
except ValueError:
|
||||||
|
discard
|
||||||
|
|
||||||
|
# finally using default
|
||||||
|
let g = parseEnum[Bar]("Baz", V)
|
||||||
|
doAssert g == V
|
||||||
|
|
||||||
|
block: # check ambiguous enum fails to parse
|
||||||
|
type
|
||||||
|
Ambig = enum
|
||||||
|
f1 = "A"
|
||||||
|
f2 = "B"
|
||||||
|
f3 = "A"
|
||||||
|
|
||||||
|
doAssert not compiles((let a = parseEnum[Ambig]("A")))
|
||||||
|
|
||||||
|
block: # check almost ambiguous enum
|
||||||
|
type
|
||||||
|
AlmostAmbig = enum
|
||||||
|
f1 = "someA"
|
||||||
|
f2 = "someB"
|
||||||
|
f3 = "SomeA"
|
||||||
|
|
||||||
|
let a = parseEnum[AlmostAmbig]("someA")
|
||||||
|
let b = parseEnum[AlmostAmbig]("someB")
|
||||||
|
let c = parseEnum[AlmostAmbig]("SomeA")
|
||||||
|
doAssert a == f1
|
||||||
|
doAssert b == f2
|
||||||
|
doAssert c == f3
|
||||||
|
|
||||||
|
block: # parseEnum TODO: merge above
|
||||||
|
type MyEnum = enum enA, enB, enC, enuD, enE
|
||||||
|
doAssert parseEnum[MyEnum]("enu_D") == enuD
|
||||||
|
|
||||||
|
doAssert parseEnum("invalid enum value", enC) == enC
|
||||||
|
|
||||||
|
block: # indentation
|
||||||
|
assert 0 == indentation """
|
||||||
|
hey
|
||||||
|
low
|
||||||
|
there
|
||||||
|
"""
|
||||||
|
assert 2 == indentation """
|
||||||
|
hey
|
||||||
|
low
|
||||||
|
there
|
||||||
|
"""
|
||||||
|
assert 2 == indentation """ hey
|
||||||
|
low
|
||||||
|
there
|
||||||
|
"""
|
||||||
|
assert 2 == indentation """ hey
|
||||||
|
low
|
||||||
|
there"""
|
||||||
|
assert 0 == indentation ""
|
||||||
|
assert 0 == indentation " \n \n"
|
||||||
|
assert 0 == indentation " "
|
||||||
|
|
||||||
|
block: # indent
|
||||||
|
doAssert " foo\n bar".indent(4, "Q") == "QQQQ foo\nQQQQ bar"
|
||||||
|
|
||||||
|
block: # unindent
|
||||||
|
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"
|
||||||
|
|
||||||
|
block: # formatBiggestFloat
|
||||||
|
disableVm:
|
||||||
|
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"]
|
||||||
|
block: # formatFloat
|
||||||
|
disableVm:
|
||||||
|
# bug #6589
|
||||||
|
when not defined(js):
|
||||||
|
doAssert formatFloat(123.456, ffScientific, precision = -1) == "1.234560e+02"
|
||||||
|
|
||||||
|
block: # `%`
|
||||||
|
doAssert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c"
|
||||||
|
doAssert "${1}12 ${-1}$2" % ["a", "b"] == "a12 bb"
|
||||||
|
doAssert "$animal eats $food." % ["animal", "The cat", "food", "fish"] ==
|
||||||
|
"The cat eats fish."
|
||||||
|
|
||||||
|
block: # formatSize
|
||||||
|
disableVm:
|
||||||
|
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
|
||||||
|
disableVm:
|
||||||
|
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"
|
||||||
|
|
||||||
|
block: # align
|
||||||
|
doAssert align("abc", 4) == " abc"
|
||||||
|
doAssert align("a", 0) == "a"
|
||||||
|
doAssert align("1232", 6) == " 1232"
|
||||||
|
doAssert align("1232", 6, '#') == "##1232"
|
||||||
|
|
||||||
|
block: # alignLeft
|
||||||
|
doAssert alignLeft("abc", 4) == "abc "
|
||||||
|
doAssert alignLeft("a", 0) == "a"
|
||||||
|
doAssert alignLeft("1232", 6) == "1232 "
|
||||||
|
doAssert alignLeft("1232", 6, '#') == "1232##"
|
||||||
|
|
||||||
|
block: # center
|
||||||
|
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"
|
||||||
|
|
||||||
|
block: # count
|
||||||
|
doAssert count("foofoofoo", "foofoo") == 1
|
||||||
|
doAssert count("foofoofoo", "foofoo", overlapping = true) == 2
|
||||||
|
doAssert count("foofoofoo", 'f') == 3
|
||||||
|
doAssert count("foofoofoobar", {'f', 'b'}) == 4
|
||||||
|
|
||||||
|
block: # isAlphaAscii
|
||||||
|
doAssert isAlphaAscii('r')
|
||||||
|
doAssert isAlphaAscii('A')
|
||||||
|
doAssert(not isAlphaAscii('$'))
|
||||||
|
|
||||||
|
block: # isAlphaNumeric
|
||||||
|
doAssert isAlphaNumeric('3')
|
||||||
|
doAssert isAlphaNumeric('R')
|
||||||
|
doAssert(not isAlphaNumeric('!'))
|
||||||
|
|
||||||
|
block: # isDigit
|
||||||
|
doAssert isDigit('3')
|
||||||
|
doAssert(not isDigit('a'))
|
||||||
|
doAssert(not isDigit('%'))
|
||||||
|
|
||||||
|
block: # isSpaceAscii
|
||||||
|
doAssert isSpaceAscii('\t')
|
||||||
|
doAssert isSpaceAscii('\l')
|
||||||
|
doAssert(not isSpaceAscii('A'))
|
||||||
|
|
||||||
|
block: # isEmptyOrWhitespace
|
||||||
|
doAssert(isEmptyOrWhitespace(""))
|
||||||
|
doAssert(isEmptyOrWhitespace(" "))
|
||||||
|
doAssert(isEmptyOrWhitespace("\t\l \v\r\f"))
|
||||||
|
doAssert(not isEmptyOrWhitespace("ABc \td"))
|
||||||
|
|
||||||
|
block: # isLowerAscii
|
||||||
|
doAssert isLowerAscii('a')
|
||||||
|
doAssert isLowerAscii('z')
|
||||||
|
doAssert(not isLowerAscii('A'))
|
||||||
|
doAssert(not isLowerAscii('5'))
|
||||||
|
doAssert(not isLowerAscii('&'))
|
||||||
|
doAssert(not isLowerAscii(' '))
|
||||||
|
|
||||||
|
block: # isUpperAscii
|
||||||
|
doAssert isUpperAscii('A')
|
||||||
|
doAssert(not isUpperAscii('b'))
|
||||||
|
doAssert(not isUpperAscii('5'))
|
||||||
|
doAssert(not isUpperAscii('%'))
|
||||||
|
|
||||||
|
block: # unescape
|
||||||
|
doAssert(unescape(r"\x013", "", "") == "\x013")
|
||||||
|
|
||||||
|
block: # join
|
||||||
|
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"
|
||||||
|
|
||||||
|
block: # startsWith / endsWith
|
||||||
|
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
|
||||||
|
|
||||||
|
static: main()
|
||||||
|
main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue