summary refs log tree commit diff stats
path: root/tests/stdlib/tstrutils.nim
diff options
context:
space:
mode:
Diffstat (limited to 'tests/stdlib/tstrutils.nim')
-rw-r--r--tests/stdlib/tstrutils.nim277
1 files changed, 244 insertions, 33 deletions
diff --git a/tests/stdlib/tstrutils.nim b/tests/stdlib/tstrutils.nim
index a6248d1e3..35f6bc669 100644
--- a/tests/stdlib/tstrutils.nim
+++ b/tests/stdlib/tstrutils.nim
@@ -1,9 +1,11 @@
 discard """
-  targets: "c cpp js"
+  matrix: "--mm:refc; --mm:orc; --backend:cpp; --backend:js --jsbigint64:off -d:nimStringHash2; --backend:js --jsbigint64:on"
 """
 
 import std/strutils
-
+from stdtest/testutils import disableVm
+import std/assertions
+import std/private/jsutils
 # xxx each instance of `disableVm` and `when not defined js:` should eventually be fixed
 
 template rejectParse(e) =
@@ -12,10 +14,6 @@ template rejectParse(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"
@@ -55,6 +53,15 @@ template main() =
     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  "]
+    # Empty string:
+    doAssert "".split() == @[""]
+    doAssert "".split(" ") == @[""]
+    doAssert "".split({' '}) == @[""]
+    # Empty separators:
+    doAssert "".split({}) == @[""]
+    doAssert "".split("") == @[""]
+    doAssert s.split({}) == @[s]
+    doAssert s.split("") == @[s]
 
   block: # splitLines
     let fixture = "a\nb\rc\r\nd"
@@ -65,12 +72,21 @@ template main() =
   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 ", 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"]
+    # Empty string:
+    doAssert "".rsplit() == @[""]
+    doAssert "".rsplit(" ") == @[""]
+    doAssert "".rsplit({' '}) == @[""]
+    # Empty separators:
+    let s = " this is an example  "
+    doAssert "".rsplit({}) == @[""]
+    doAssert "".rsplit("") == @[""]
+    doAssert s.rsplit({}) == @[s]
+    doAssert s.rsplit("") == @[s]
 
   block: # splitWhitespace
     let s = " this is an example  "
@@ -202,7 +218,30 @@ template main() =
     s.removePrefix("")
     doAssert s == "\r\n\r\nhello"
 
-  block: # delete
+  block: # delete(slice)
+    var s = "0123456789ABCDEFGH"
+    delete(s, 4 .. 5)
+    doAssert s == "01236789ABCDEFGH"
+    delete(s, s.len-1 .. s.len-1)
+    doAssert s == "01236789ABCDEFG"
+    delete(s, 0..0)
+    doAssert s == "1236789ABCDEFG"
+    s = ""
+    doAssertRaises(IndexDefect): delete(s, 0..0)
+    doAssert s == ""
+    s = "abc"
+    doAssertRaises(IndexDefect): delete(s, -1 .. -2)
+    doAssertRaises(IndexDefect): delete(s, 2..3)
+    doAssertRaises(IndexDefect): delete(s, 3..2)
+    delete(s, 2..2)
+    doAssert s == "ab"
+    delete(s, 1..0)
+    doAssert s == "ab"
+    delete(s, 0..0)
+    doAssert s == "b"
+
+  block: # delete(first, last)
+    {.push warning[deprecated]:off.}
     var s = "0123456789ABCDEFGH"
     delete(s, 4, 5)
     doAssert s == "01236789ABCDEFGH"
@@ -210,20 +249,88 @@ template main() =
     doAssert s == "01236789ABCDEFG"
     delete(s, 0, 0)
     doAssert s == "1236789ABCDEFG"
+    {.pop.}
 
   block: # find
-    doAssert "0123456789ABCDEFGH".find('A') == 10
-    doAssert "0123456789ABCDEFGH".find('A', 5) == 10
-    doAssert "0123456789ABCDEFGH".find('A', 5, 10) == 10
-    doAssert "0123456789ABCDEFGH".find('A', 5, 9) == -1
-    doAssert "0123456789ABCDEFGH".find("A") == 10
-    doAssert "0123456789ABCDEFGH".find("A", 5) == 10
-    doAssert "0123456789ABCDEFGH".find("A", 5, 10) == 10
-    doAssert "0123456789ABCDEFGH".find("A", 5, 9) == -1
-    doAssert "0123456789ABCDEFGH".find({'A'..'C'}) == 10
-    doAssert "0123456789ABCDEFGH".find({'A'..'C'}, 5) == 10
-    doAssert "0123456789ABCDEFGH".find({'A'..'C'}, 5, 10) == 10
-    doAssert "0123456789ABCDEFGH".find({'A'..'C'}, 5, 9) == -1
+    const haystack: string = "0123456789ABCDEFGH"
+    doAssert haystack.find('A') == 10
+    doAssert haystack.find('A', 5) == 10
+    doAssert haystack.find('A', 5, 10) == 10
+    doAssert haystack.find('A', 5, 9) == -1
+    doAssert haystack.find("A") == 10
+    doAssert haystack.find("A", 5) == 10
+    doAssert haystack.find("A", 5, 10) == 10
+    doAssert haystack.find("A", 5, 9) == -1
+    doAssert haystack.find({'A'..'C'}) == 10
+    doAssert haystack.find({'A'..'C'}, 5) == 10
+    doAssert haystack.find({'A'..'C'}, 5, 10) == 10
+    doAssert haystack.find({'A'..'C'}, 5, 9) == -1
+    doAssert haystack.find('A', 0, 0) == -1 # search limited to the first char
+    doAssert haystack.find('A', 5, 0) == -1 # last < start
+    doAssert haystack.find('A', 5, 4) == -1 # last < start
+
+    block:
+      const haystack: string = "ABCABABABABCAB"
+      doAssert haystack.len == 14
+
+      # only last argument
+      doAssert haystack.find("ABC") == 0
+      doAssert haystack.find("ABC", last=13) == 0 # after the second ABC
+      doAssert haystack.find("ABC", last=5) == 0 # before the second ABC
+
+      # only start argument
+      doAssert haystack.find("ABC", start=0) == 0
+      doAssert haystack.find("ABC", start=1) == 9
+      doAssert haystack.find("ABC", start=9) == 9
+      doAssert haystack.find("ABC", start=10) == -1
+
+      # both start and last arguments
+      doAssert haystack.find("ABC", start=0, last=14) == 0
+      doAssert haystack.find("ABC", start=0, last=13) == 0
+      doAssert haystack.find("ABC", start=0, last=12) == 0
+      doAssert haystack.find("ABC", start=1, last=13) == 9
+      doAssert haystack.find("ABC", start=1, last=12) == 9
+      doAssert haystack.find("ABC", start=1, last=11) == 9
+      doAssert haystack.find("ABC", start=1, last=10) == -1
+
+    doAssert "".find("/") == -1
+    doAssert "/".find("/") == 0
+    doAssert "/".find("//") == -1
+    doAssert "///".find("//", start=3) == -1
+
+    # searching for empty string
+    doAssert "".find("") == 0
+    doAssert "abc".find("") == 0
+    doAssert "abc".find("", start=1) == 1
+    doAssert "abc".find("", start=2) == 2
+    doAssert "abc".find("", start=3) == 3
+    doAssert "abc".find("", start=4) == -1
+    doAssert "abc".find("", start=400) == -1
+    doAssert "abc".find("", start=1, last=3) == 1
+    doAssert "abc".find("", start=1, last=2) == 1
+    doAssert "abc".find("", start=1, last=1) == 1
+    doAssert "abc".find("", start=1, last=0) == 1
+    doAssert "abc".find("", start=1, last = -1) == 1
+
+    # when last <= start, searching for non-empty string
+    block:
+      let last: int = -1 # searching through whole line
+      doAssert "abcd".find("ab", start=0, last=last) == 0
+      doAssert "abcd".find("ab", start=1, last=last) == -1
+      doAssert "abcd".find("bc", start=1, last=last) == 1
+      doAssert "abcd".find("bc", start=2, last=last) == -1
+    block:
+      let last: int = 0
+      doAssert "abcd".find("ab", start=0, last=last) == -1
+      doAssert "abcd".find("ab", start=1, last=last) == -1
+      doAssert "abcd".find("bc", start=1, last=last) == -1
+      doAssert "abcd".find("bc", start=2, last=last) == -1
+    block:
+      let last: int = 1
+      doAssert "abcd".find("ab", start=0, last=last) == 0
+      doAssert "abcd".find("ab", start=1, last=last) == -1
+      doAssert "abcd".find("bc", start=1, last=last) == -1
+      doAssert "abcd".find("bc", start=2, last=last) == -1
 
   block: # rfind
     doAssert "0123456789ABCDEFGAH".rfind('A') == 17
@@ -247,6 +354,70 @@ template main() =
     doAssert "/1/2/3".rfind('/', last=1) == 0
     doAssert "/1/2/3".rfind('0') == -1
 
+    block:
+      const haystack: string = "ABCABABABABCAB"
+      doAssert haystack.len == 14
+      doAssert haystack.rfind("ABC") == 9
+      doAssert haystack.rfind("ABC", last=13) == 9
+      doAssert haystack.rfind("ABC", last=12) == 9
+      doAssert haystack.rfind("ABC", last=11) == 9
+      doAssert haystack.rfind("ABC", last=10) == 0
+
+      doAssert haystack.rfind("ABC", start=0) == 9
+      doAssert haystack.rfind("ABC", start=1) == 9
+      doAssert haystack.rfind("ABC", start=9) == 9
+      doAssert haystack.rfind("ABC", start=10) == -1
+
+      doAssert haystack.rfind("ABC", start=0, last=13) == 9
+      doAssert haystack.rfind("ABC", start=0, last=12) == 9
+      doAssert haystack.rfind("ABC", start=0, last=11) == 9
+      doAssert haystack.rfind("ABC", start=0, last=10) == 0
+      doAssert haystack.rfind("ABC", start=1, last=10) == -1
+
+    doAssert "".rfind("/") == -1
+    doAssert "/".rfind("/") == 0
+    doAssert "/".rfind("//") == -1
+    doAssert "///".rfind("//", start=3) == -1
+
+    # searching for empty string
+    doAssert "".rfind("") == 0
+    doAssert "abc".rfind("") == 3
+    doAssert "abc".rfind("", start=1) == 3
+    doAssert "abc".rfind("", start=2) == 3
+    doAssert "abc".rfind("", start=3) == 3
+    doAssert "abc".rfind("", start=4) == 4
+    doAssert "abc".rfind("", start=400) == 400
+
+    doAssert "abc".rfind("", start=1, last=3) == 3
+    doAssert "abc".rfind("", start=1, last=2) == 2
+    doAssert "abc".rfind("", start=1, last=1) == 1
+    # This returns the start index instead of the last index
+    # because start > last
+    doAssert "abc".rfind("", start=1, last=0) == 1
+    doAssert "abc".rfind("", start=1, last = -1) == 3
+    
+    doAssert "abc".rfind("", start=0, last=0) == 0
+
+    # when last <= start, searching for non-empty string
+    block:
+      let last: int = -1
+      doAssert "abcd".rfind("ab", start=0, last=last) == 0
+      doAssert "abcd".rfind("ab", start=1, last=last) == -1
+      doAssert "abcd".rfind("bc", start=1, last=last) == 1
+      doAssert "abcd".rfind("bc", start=2, last=last) == -1
+    block:
+      let last: int = 0
+      doAssert "abcd".rfind("ab", start=0, last=last) == -1
+      doAssert "abcd".rfind("ab", start=1, last=last) == -1
+      doAssert "abcd".rfind("bc", start=1, last=last) == -1
+      doAssert "abcd".rfind("bc", start=2, last=last) == -1
+    block:
+      let last: int = 1
+      doAssert "abcd".rfind("ab", start=0, last=last) == 0
+      doAssert "abcd".rfind("ab", start=1, last=last) == -1
+      doAssert "abcd".rfind("bc", start=1, last=last) == -1
+      doAssert "abcd".rfind("bc", start=2, last=last) == -1
+
   block: # trimZeros
     var x = "1200"
     x.trimZeros()
@@ -281,6 +452,9 @@ template main() =
     x = "1e0"
     x.trimZeros()
     doAssert x == "1e0"
+    x = "1.23"
+    x.trimZeros()
+    doAssert x == "1.23"
 
   block: # countLines
     proc assertCountLines(s: string) = doAssert s.countLines == s.splitLines.len
@@ -353,8 +527,9 @@ template main() =
 
   block: # toHex
     doAssert(toHex(100i16, 32) == "00000000000000000000000000000064")
-    doAssert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C")
-    when not defined js:
+    whenJsNoBigInt64: discard
+    do:
+      doAssert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C")
       doAssert(toHex(high(uint64)) == "FFFFFFFFFFFFFFFF")
       doAssert(toHex(high(uint64), 16) == "FFFFFFFFFFFFFFFF")
       doAssert(toHex(high(uint64), 32) == "0000000000000000FFFFFFFFFFFFFFFF")
@@ -375,11 +550,12 @@ template main() =
     doAssert(spaces(0) == "")
 
   block: # toBin, toOct
-    block:# bug #11369
+    whenJsNoBigInt64: # bug #11369
+      discard
+    do:
       var num: int64 = -1
-      when not defined js:
-        doAssert num.toBin(64) == "1111111111111111111111111111111111111111111111111111111111111111"
-        doAssert num.toOct(24) == "001777777777777777777777"
+      doAssert num.toBin(64) == "1111111111111111111111111111111111111111111111111111111111111111"
+      doAssert num.toOct(24) == "001777777777777777777777"
 
   block: # replace
     doAssert "oo".replace("", "abc") == "oo"
@@ -440,6 +616,17 @@ template main() =
       let g = parseEnum[Foo]("Bar", A)
       doAssert g == A
 
+    block: # bug #19463
+      const CAMPAIGN_TABLE = "wikientries_campaign"
+      const CHARACTER_TABLE = "wikientries_character"
+
+      type Tables = enum
+        a = CAMPAIGN_TABLE,
+        b = CHARACTER_TABLE,
+
+      let myA = CAMPAIGN_TABLE
+      doAssert $parseEnum[Tables](myA) == "wikientries_campaign"
+
     block: # check enum defined in block
       type
         Bar = enum
@@ -492,11 +679,22 @@ template main() =
       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:
+      type MyEnum = enum enA, enB, enC, enuD, enE
+      doAssert parseEnum[MyEnum]("enu_D") == enuD
+
+      doAssert parseEnum("invalid enum value", enC) == enC
+    
+    block: # issue #22726
+      type SomeEnum = enum A, B, C
+
+      proc assignEnum(dest: var enum, s: string) =
+        type ty = typeof(dest)
+        dest = parseEnum[ty](s)
+      
+      var v: SomeEnum
+      v.assignEnum("A")
+      doAssert v == A
 
   block: # indentation
     doAssert 0 == indentation """
@@ -575,7 +773,8 @@ bar
 
   block: # formatSize
     disableVm:
-      when not defined(js):
+      whenJsNoBigInt64: discard
+      do:
         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"
@@ -698,5 +897,17 @@ bar
     doAssert s.endsWith('a') == false
     doAssert s.endsWith('\0') == false
 
+  block: # nimIdentNormalize
+    doAssert nimIdentNormalize("") == ""
+    doAssert nimIdentNormalize("foo") == "foo"
+    doAssert nimIdentNormalize("foo_bar") == "foobar"
+    doAssert nimIdentNormalize("Foo_bar") == "Foobar"
+    doAssert nimIdentNormalize("_Foo_bar") == "_foobar"
+
+  block: # bug #19500
+    doAssert "abc \0 def".find("def") == 6
+    doAssert "abc \0 def".find('d') == 6
+
+
 static: main()
 main()