remove isMainModule from json,os,sequtils (#14572)
* move json.isMainModule => tjson * move isMainModule => tos,tsequtils
This commit is contained in:
parent
b19ad22b90
commit
d573581eb7
6 changed files with 759 additions and 757 deletions
|
|
@ -1065,464 +1065,3 @@ iterator items*[T](xs: iterator: T): T =
|
||||||
## templates.
|
## templates.
|
||||||
for x in xs():
|
for x in xs():
|
||||||
yield x
|
yield x
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
import strutils
|
|
||||||
from algorithm import sorted
|
|
||||||
|
|
||||||
# helper for testing double substitution side effects which are handled
|
|
||||||
# by `evalOnceAs`
|
|
||||||
var counter = 0
|
|
||||||
proc identity[T](a: T): auto =
|
|
||||||
counter.inc
|
|
||||||
a
|
|
||||||
|
|
||||||
block: # concat test
|
|
||||||
let
|
|
||||||
s1 = @[1, 2, 3]
|
|
||||||
s2 = @[4, 5]
|
|
||||||
s3 = @[6, 7]
|
|
||||||
total = concat(s1, s2, s3)
|
|
||||||
assert total == @[1, 2, 3, 4, 5, 6, 7]
|
|
||||||
|
|
||||||
block: # count test
|
|
||||||
let
|
|
||||||
s1 = @[1, 2, 3, 2]
|
|
||||||
s2 = @['a', 'b', 'x', 'a']
|
|
||||||
a1 = [1, 2, 3, 2]
|
|
||||||
a2 = ['a', 'b', 'x', 'a']
|
|
||||||
r0 = count(s1, 0)
|
|
||||||
r1 = count(s1, 1)
|
|
||||||
r2 = count(s1, 2)
|
|
||||||
r3 = count(s2, 'y')
|
|
||||||
r4 = count(s2, 'x')
|
|
||||||
r5 = count(s2, 'a')
|
|
||||||
ar0 = count(a1, 0)
|
|
||||||
ar1 = count(a1, 1)
|
|
||||||
ar2 = count(a1, 2)
|
|
||||||
ar3 = count(a2, 'y')
|
|
||||||
ar4 = count(a2, 'x')
|
|
||||||
ar5 = count(a2, 'a')
|
|
||||||
assert r0 == 0
|
|
||||||
assert r1 == 1
|
|
||||||
assert r2 == 2
|
|
||||||
assert r3 == 0
|
|
||||||
assert r4 == 1
|
|
||||||
assert r5 == 2
|
|
||||||
assert ar0 == 0
|
|
||||||
assert ar1 == 1
|
|
||||||
assert ar2 == 2
|
|
||||||
assert ar3 == 0
|
|
||||||
assert ar4 == 1
|
|
||||||
assert ar5 == 2
|
|
||||||
|
|
||||||
block: # cycle tests
|
|
||||||
let
|
|
||||||
a = @[1, 2, 3]
|
|
||||||
b: seq[int] = @[]
|
|
||||||
c = [1, 2, 3]
|
|
||||||
|
|
||||||
doAssert a.cycle(3) == @[1, 2, 3, 1, 2, 3, 1, 2, 3]
|
|
||||||
doAssert a.cycle(0) == @[]
|
|
||||||
#doAssert a.cycle(-1) == @[] # will not compile!
|
|
||||||
doAssert b.cycle(3) == @[]
|
|
||||||
doAssert c.cycle(3) == @[1, 2, 3, 1, 2, 3, 1, 2, 3]
|
|
||||||
doAssert c.cycle(0) == @[]
|
|
||||||
|
|
||||||
block: # repeat tests
|
|
||||||
assert repeat(10, 5) == @[10, 10, 10, 10, 10]
|
|
||||||
assert repeat(@[1, 2, 3], 2) == @[@[1, 2, 3], @[1, 2, 3]]
|
|
||||||
assert repeat([1, 2, 3], 2) == @[[1, 2, 3], [1, 2, 3]]
|
|
||||||
|
|
||||||
block: # deduplicates test
|
|
||||||
let
|
|
||||||
dup1 = @[1, 1, 3, 4, 2, 2, 8, 1, 4]
|
|
||||||
dup2 = @["a", "a", "c", "d", "d"]
|
|
||||||
dup3 = [1, 1, 3, 4, 2, 2, 8, 1, 4]
|
|
||||||
dup4 = ["a", "a", "c", "d", "d"]
|
|
||||||
unique1 = deduplicate(dup1)
|
|
||||||
unique2 = deduplicate(dup2)
|
|
||||||
unique3 = deduplicate(dup3)
|
|
||||||
unique4 = deduplicate(dup4)
|
|
||||||
unique5 = deduplicate(dup1.sorted, true)
|
|
||||||
unique6 = deduplicate(dup2, true)
|
|
||||||
unique7 = deduplicate(dup3.sorted, true)
|
|
||||||
unique8 = deduplicate(dup4, true)
|
|
||||||
assert unique1 == @[1, 3, 4, 2, 8]
|
|
||||||
assert unique2 == @["a", "c", "d"]
|
|
||||||
assert unique3 == @[1, 3, 4, 2, 8]
|
|
||||||
assert unique4 == @["a", "c", "d"]
|
|
||||||
assert unique5 == @[1, 2, 3, 4, 8]
|
|
||||||
assert unique6 == @["a", "c", "d"]
|
|
||||||
assert unique7 == @[1, 2, 3, 4, 8]
|
|
||||||
assert unique8 == @["a", "c", "d"]
|
|
||||||
|
|
||||||
block: # zip test
|
|
||||||
let
|
|
||||||
short = @[1, 2, 3]
|
|
||||||
long = @[6, 5, 4, 3, 2, 1]
|
|
||||||
words = @["one", "two", "three"]
|
|
||||||
ashort = [1, 2, 3]
|
|
||||||
along = [6, 5, 4, 3, 2, 1]
|
|
||||||
awords = ["one", "two", "three"]
|
|
||||||
zip1 = zip(short, long)
|
|
||||||
zip2 = zip(short, words)
|
|
||||||
zip3 = zip(ashort, along)
|
|
||||||
assert zip1 == @[(1, 6), (2, 5), (3, 4)]
|
|
||||||
assert zip2 == @[(1, "one"), (2, "two"), (3, "three")]
|
|
||||||
assert zip3 == @[(1, 6), (2, 5), (3, 4)]
|
|
||||||
assert zip1[2][1] == 4
|
|
||||||
assert zip2[2][1] == "three"
|
|
||||||
assert zip3[2][1] == 4
|
|
||||||
when (NimMajor, NimMinor) <= (1, 0):
|
|
||||||
let
|
|
||||||
# In Nim 1.0.x and older, zip returned a seq of tuple strictly
|
|
||||||
# with fields named "a" and "b".
|
|
||||||
zipAb = zip(ashort, awords)
|
|
||||||
assert zipAb == @[(a: 1, b: "one"), (2, "two"), (3, "three")]
|
|
||||||
assert zipAb[2].b == "three"
|
|
||||||
else:
|
|
||||||
let
|
|
||||||
# As zip returns seq of anonymous tuples, they can be assigned
|
|
||||||
# to any variable that's a sequence of named tuples too.
|
|
||||||
zipXy: seq[tuple[x: int, y: string]] = zip(ashort, awords)
|
|
||||||
zipMn: seq[tuple[m: int, n: string]] = zip(ashort, words)
|
|
||||||
assert zipXy == @[(x: 1, y: "one"), (2, "two"), (3, "three")]
|
|
||||||
assert zipMn == @[(m: 1, n: "one"), (2, "two"), (3, "three")]
|
|
||||||
assert zipXy[2].y == "three"
|
|
||||||
assert zipMn[2].n == "three"
|
|
||||||
|
|
||||||
block: # distribute tests
|
|
||||||
let numbers = @[1, 2, 3, 4, 5, 6, 7]
|
|
||||||
doAssert numbers.distribute(3) == @[@[1, 2, 3], @[4, 5], @[6, 7]]
|
|
||||||
doAssert numbers.distribute(6)[0] == @[1, 2]
|
|
||||||
doAssert numbers.distribute(6)[5] == @[7]
|
|
||||||
let a = @[1, 2, 3, 4, 5, 6, 7]
|
|
||||||
doAssert a.distribute(1, true) == @[@[1, 2, 3, 4, 5, 6, 7]]
|
|
||||||
doAssert a.distribute(1, false) == @[@[1, 2, 3, 4, 5, 6, 7]]
|
|
||||||
doAssert a.distribute(2, true) == @[@[1, 2, 3, 4], @[5, 6, 7]]
|
|
||||||
doAssert a.distribute(2, false) == @[@[1, 2, 3, 4], @[5, 6, 7]]
|
|
||||||
doAssert a.distribute(3, true) == @[@[1, 2, 3], @[4, 5], @[6, 7]]
|
|
||||||
doAssert a.distribute(3, false) == @[@[1, 2, 3], @[4, 5, 6], @[7]]
|
|
||||||
doAssert a.distribute(4, true) == @[@[1, 2], @[3, 4], @[5, 6], @[7]]
|
|
||||||
doAssert a.distribute(4, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7]]
|
|
||||||
doAssert a.distribute(5, true) == @[@[1, 2], @[3, 4], @[5], @[6], @[7]]
|
|
||||||
doAssert a.distribute(5, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7], @[]]
|
|
||||||
doAssert a.distribute(6, true) == @[@[1, 2], @[3], @[4], @[5], @[6], @[7]]
|
|
||||||
doAssert a.distribute(6, false) == @[
|
|
||||||
@[1, 2], @[3, 4], @[5, 6], @[7], @[], @[]]
|
|
||||||
doAssert a.distribute(8, false) == a.distribute(8, true)
|
|
||||||
doAssert a.distribute(90, false) == a.distribute(90, true)
|
|
||||||
var b = @[0]
|
|
||||||
for f in 1 .. 25: b.add(f)
|
|
||||||
doAssert b.distribute(5, true)[4].len == 5
|
|
||||||
doAssert b.distribute(5, false)[4].len == 2
|
|
||||||
|
|
||||||
block: # map test
|
|
||||||
let
|
|
||||||
numbers = @[1, 4, 5, 8, 9, 7, 4]
|
|
||||||
anumbers = [1, 4, 5, 8, 9, 7, 4]
|
|
||||||
m1 = map(numbers, proc(x: int): int = 2*x)
|
|
||||||
m2 = map(anumbers, proc(x: int): int = 2*x)
|
|
||||||
assert m1 == @[2, 8, 10, 16, 18, 14, 8]
|
|
||||||
assert m2 == @[2, 8, 10, 16, 18, 14, 8]
|
|
||||||
|
|
||||||
block: # apply test
|
|
||||||
var a = @["1", "2", "3", "4"]
|
|
||||||
apply(a, proc(x: var string) = x &= "42")
|
|
||||||
assert a == @["142", "242", "342", "442"]
|
|
||||||
|
|
||||||
block: # filter proc test
|
|
||||||
let
|
|
||||||
colors = @["red", "yellow", "black"]
|
|
||||||
acolors = ["red", "yellow", "black"]
|
|
||||||
f1 = filter(colors, proc(x: string): bool = x.len < 6)
|
|
||||||
f2 = filter(colors) do (x: string) -> bool: x.len > 5
|
|
||||||
f3 = filter(acolors, proc(x: string): bool = x.len < 6)
|
|
||||||
f4 = filter(acolors) do (x: string) -> bool: x.len > 5
|
|
||||||
assert f1 == @["red", "black"]
|
|
||||||
assert f2 == @["yellow"]
|
|
||||||
assert f3 == @["red", "black"]
|
|
||||||
assert f4 == @["yellow"]
|
|
||||||
|
|
||||||
block: # filter iterator test
|
|
||||||
let numbers = @[1, 4, 5, 8, 9, 7, 4]
|
|
||||||
let anumbers = [1, 4, 5, 8, 9, 7, 4]
|
|
||||||
assert toSeq(filter(numbers, proc (x: int): bool = x mod 2 == 0)) ==
|
|
||||||
@[4, 8, 4]
|
|
||||||
assert toSeq(filter(anumbers, proc (x: int): bool = x mod 2 == 0)) ==
|
|
||||||
@[4, 8, 4]
|
|
||||||
|
|
||||||
block: # keepIf test
|
|
||||||
var floats = @[13.0, 12.5, 5.8, 2.0, 6.1, 9.9, 10.1]
|
|
||||||
keepIf(floats, proc(x: float): bool = x > 10)
|
|
||||||
assert floats == @[13.0, 12.5, 10.1]
|
|
||||||
|
|
||||||
block: # delete tests
|
|
||||||
let outcome = @[1, 1, 1, 1, 1, 1, 1, 1]
|
|
||||||
var dest = @[1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1]
|
|
||||||
dest.delete(3, 8)
|
|
||||||
assert outcome == dest, """\
|
|
||||||
Deleting range 3-9 from [1,1,1,2,2,2,2,2,2,1,1,1,1,1]
|
|
||||||
is [1,1,1,1,1,1,1,1]"""
|
|
||||||
var x = @[1, 2, 3]
|
|
||||||
x.delete(100, 100)
|
|
||||||
assert x == @[1, 2, 3]
|
|
||||||
|
|
||||||
block: # insert tests
|
|
||||||
var dest = @[1, 1, 1, 1, 1, 1, 1, 1]
|
|
||||||
let
|
|
||||||
src = @[2, 2, 2, 2, 2, 2]
|
|
||||||
outcome = @[1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1]
|
|
||||||
dest.insert(src, 3)
|
|
||||||
assert dest == outcome, """\
|
|
||||||
Inserting [2,2,2,2,2,2] into [1,1,1,1,1,1,1,1]
|
|
||||||
at 3 is [1,1,1,2,2,2,2,2,2,1,1,1,1,1]"""
|
|
||||||
|
|
||||||
block: # filterIt test
|
|
||||||
let
|
|
||||||
temperatures = @[-272.15, -2.0, 24.5, 44.31, 99.9, -113.44]
|
|
||||||
acceptable = filterIt(temperatures, it < 50 and it > -10)
|
|
||||||
notAcceptable = filterIt(temperatures, it > 50 or it < -10)
|
|
||||||
assert acceptable == @[-2.0, 24.5, 44.31]
|
|
||||||
assert notAcceptable == @[-272.15, 99.9, -113.44]
|
|
||||||
|
|
||||||
block: # keepItIf test
|
|
||||||
var candidates = @["foo", "bar", "baz", "foobar"]
|
|
||||||
keepItIf(candidates, it.len == 3 and it[0] == 'b')
|
|
||||||
assert candidates == @["bar", "baz"]
|
|
||||||
|
|
||||||
block: # all
|
|
||||||
let
|
|
||||||
numbers = @[1, 4, 5, 8, 9, 7, 4]
|
|
||||||
anumbers = [1, 4, 5, 8, 9, 7, 4]
|
|
||||||
len0seq: seq[int] = @[]
|
|
||||||
assert all(numbers, proc (x: int): bool = return x < 10) == true
|
|
||||||
assert all(numbers, proc (x: int): bool = return x < 9) == false
|
|
||||||
assert all(len0seq, proc (x: int): bool = return false) == true
|
|
||||||
assert all(anumbers, proc (x: int): bool = return x < 10) == true
|
|
||||||
assert all(anumbers, proc (x: int): bool = return x < 9) == false
|
|
||||||
|
|
||||||
block: # allIt
|
|
||||||
let
|
|
||||||
numbers = @[1, 4, 5, 8, 9, 7, 4]
|
|
||||||
anumbers = [1, 4, 5, 8, 9, 7, 4]
|
|
||||||
len0seq: seq[int] = @[]
|
|
||||||
assert allIt(numbers, it < 10) == true
|
|
||||||
assert allIt(numbers, it < 9) == false
|
|
||||||
assert allIt(len0seq, false) == true
|
|
||||||
assert allIt(anumbers, it < 10) == true
|
|
||||||
assert allIt(anumbers, it < 9) == false
|
|
||||||
|
|
||||||
block: # any
|
|
||||||
let
|
|
||||||
numbers = @[1, 4, 5, 8, 9, 7, 4]
|
|
||||||
anumbers = [1, 4, 5, 8, 9, 7, 4]
|
|
||||||
len0seq: seq[int] = @[]
|
|
||||||
assert any(numbers, proc (x: int): bool = return x > 8) == true
|
|
||||||
assert any(numbers, proc (x: int): bool = return x > 9) == false
|
|
||||||
assert any(len0seq, proc (x: int): bool = return true) == false
|
|
||||||
assert any(anumbers, proc (x: int): bool = return x > 8) == true
|
|
||||||
assert any(anumbers, proc (x: int): bool = return x > 9) == false
|
|
||||||
|
|
||||||
block: # anyIt
|
|
||||||
let
|
|
||||||
numbers = @[1, 4, 5, 8, 9, 7, 4]
|
|
||||||
anumbers = [1, 4, 5, 8, 9, 7, 4]
|
|
||||||
len0seq: seq[int] = @[]
|
|
||||||
assert anyIt(numbers, it > 8) == true
|
|
||||||
assert anyIt(numbers, it > 9) == false
|
|
||||||
assert anyIt(len0seq, true) == false
|
|
||||||
assert anyIt(anumbers, it > 8) == true
|
|
||||||
assert anyIt(anumbers, it > 9) == false
|
|
||||||
|
|
||||||
block: # toSeq test
|
|
||||||
block:
|
|
||||||
let
|
|
||||||
numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
||||||
oddNumbers = toSeq(filter(numeric) do (x: int) -> bool:
|
|
||||||
if x mod 2 == 1:
|
|
||||||
result = true)
|
|
||||||
assert oddNumbers == @[1, 3, 5, 7, 9]
|
|
||||||
|
|
||||||
block:
|
|
||||||
doAssert [1, 2].toSeq == @[1, 2]
|
|
||||||
doAssert @[1, 2].toSeq == @[1, 2]
|
|
||||||
|
|
||||||
doAssert @[1, 2].toSeq == @[1, 2]
|
|
||||||
doAssert toSeq(@[1, 2]) == @[1, 2]
|
|
||||||
|
|
||||||
block:
|
|
||||||
iterator myIter(seed: int): auto =
|
|
||||||
for i in 0..<seed:
|
|
||||||
yield i
|
|
||||||
doAssert toSeq(myIter(2)) == @[0, 1]
|
|
||||||
|
|
||||||
block:
|
|
||||||
iterator myIter(): auto {.inline.} =
|
|
||||||
yield 1
|
|
||||||
yield 2
|
|
||||||
|
|
||||||
doAssert myIter.toSeq == @[1, 2]
|
|
||||||
doAssert toSeq(myIter) == @[1, 2]
|
|
||||||
|
|
||||||
block:
|
|
||||||
iterator myIter(): int {.closure.} =
|
|
||||||
yield 1
|
|
||||||
yield 2
|
|
||||||
|
|
||||||
doAssert myIter.toSeq == @[1, 2]
|
|
||||||
doAssert toSeq(myIter) == @[1, 2]
|
|
||||||
|
|
||||||
block:
|
|
||||||
proc myIter(): auto =
|
|
||||||
iterator ret(): int {.closure.} =
|
|
||||||
yield 1
|
|
||||||
yield 2
|
|
||||||
result = ret
|
|
||||||
|
|
||||||
doAssert myIter().toSeq == @[1, 2]
|
|
||||||
doAssert toSeq(myIter()) == @[1, 2]
|
|
||||||
|
|
||||||
block:
|
|
||||||
proc myIter(n: int): auto =
|
|
||||||
var counter = 0
|
|
||||||
iterator ret(): int {.closure.} =
|
|
||||||
while counter < n:
|
|
||||||
yield counter
|
|
||||||
counter.inc
|
|
||||||
result = ret
|
|
||||||
|
|
||||||
block:
|
|
||||||
let myIter3 = myIter(3)
|
|
||||||
doAssert myIter3.toSeq == @[0, 1, 2]
|
|
||||||
block:
|
|
||||||
let myIter3 = myIter(3)
|
|
||||||
doAssert toSeq(myIter3) == @[0, 1, 2]
|
|
||||||
block:
|
|
||||||
# makes sure this does not hang forever
|
|
||||||
doAssert myIter(3).toSeq == @[0, 1, 2]
|
|
||||||
doAssert toSeq(myIter(3)) == @[0, 1, 2]
|
|
||||||
|
|
||||||
block:
|
|
||||||
# tests https://github.com/nim-lang/Nim/issues/7187
|
|
||||||
counter = 0
|
|
||||||
let ret = toSeq(@[1, 2, 3].identity().filter(proc (x: int): bool = x < 3))
|
|
||||||
doAssert ret == @[1, 2]
|
|
||||||
doAssert counter == 1
|
|
||||||
block: # foldl tests
|
|
||||||
let
|
|
||||||
numbers = @[5, 9, 11]
|
|
||||||
addition = foldl(numbers, a + b)
|
|
||||||
subtraction = foldl(numbers, a - b)
|
|
||||||
multiplication = foldl(numbers, a * b)
|
|
||||||
words = @["nim", "is", "cool"]
|
|
||||||
concatenation = foldl(words, a & b)
|
|
||||||
assert addition == 25, "Addition is (((5)+9)+11)"
|
|
||||||
assert subtraction == -15, "Subtraction is (((5)-9)-11)"
|
|
||||||
assert multiplication == 495, "Multiplication is (((5)*9)*11)"
|
|
||||||
assert concatenation == "nimiscool"
|
|
||||||
|
|
||||||
block: # foldr tests
|
|
||||||
let
|
|
||||||
numbers = @[5, 9, 11]
|
|
||||||
addition = foldr(numbers, a + b)
|
|
||||||
subtraction = foldr(numbers, a - b)
|
|
||||||
multiplication = foldr(numbers, a * b)
|
|
||||||
words = @["nim", "is", "cool"]
|
|
||||||
concatenation = foldr(words, a & b)
|
|
||||||
assert addition == 25, "Addition is (5+(9+(11)))"
|
|
||||||
assert subtraction == 7, "Subtraction is (5-(9-(11)))"
|
|
||||||
assert multiplication == 495, "Multiplication is (5*(9*(11)))"
|
|
||||||
assert concatenation == "nimiscool"
|
|
||||||
doAssert toSeq(1..3).foldr(a + b) == 6 # issue #14404
|
|
||||||
|
|
||||||
block: # mapIt + applyIt test
|
|
||||||
counter = 0
|
|
||||||
var
|
|
||||||
nums = @[1, 2, 3, 4]
|
|
||||||
strings = nums.identity.mapIt($(4 * it))
|
|
||||||
doAssert counter == 1
|
|
||||||
nums.applyIt(it * 3)
|
|
||||||
assert nums[0] + nums[3] == 15
|
|
||||||
assert strings[2] == "12"
|
|
||||||
|
|
||||||
block: # newSeqWith tests
|
|
||||||
var seq2D = newSeqWith(4, newSeq[bool](2))
|
|
||||||
seq2D[0][0] = true
|
|
||||||
seq2D[1][0] = true
|
|
||||||
seq2D[0][1] = true
|
|
||||||
doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]]
|
|
||||||
|
|
||||||
block: # mapLiterals tests
|
|
||||||
let x = mapLiterals([0.1, 1.2, 2.3, 3.4], int)
|
|
||||||
doAssert x is array[4, int]
|
|
||||||
doAssert mapLiterals((1, ("abc"), 2), float, nested = false) ==
|
|
||||||
(float(1), "abc", float(2))
|
|
||||||
doAssert mapLiterals(([1], ("abc"), 2), `$`, nested = true) ==
|
|
||||||
(["1"], "abc", "2")
|
|
||||||
|
|
||||||
block: # mapIt with openArray
|
|
||||||
counter = 0
|
|
||||||
proc foo(x: openArray[int]): seq[int] = x.mapIt(it * 10)
|
|
||||||
doAssert foo([identity(1), identity(2)]) == @[10, 20]
|
|
||||||
doAssert counter == 2
|
|
||||||
|
|
||||||
block: # mapIt with direct openArray
|
|
||||||
proc foo1(x: openArray[int]): seq[int] = x.mapIt(it * 10)
|
|
||||||
counter = 0
|
|
||||||
doAssert foo1(openArray[int]([identity(1), identity(2)])) == @[10, 20]
|
|
||||||
doAssert counter == 2
|
|
||||||
|
|
||||||
# Corner cases (openArray literals should not be common)
|
|
||||||
template foo2(x: openArray[int]): seq[int] = x.mapIt(it * 10)
|
|
||||||
counter = 0
|
|
||||||
doAssert foo2(openArray[int]([identity(1), identity(2)])) == @[10, 20]
|
|
||||||
# TODO: this fails; not sure how to fix this case
|
|
||||||
# doAssert counter == 2
|
|
||||||
|
|
||||||
counter = 0
|
|
||||||
doAssert openArray[int]([identity(1), identity(2)]).mapIt(it) == @[1, 2]
|
|
||||||
# ditto
|
|
||||||
# doAssert counter == 2
|
|
||||||
|
|
||||||
block: # mapIt empty test, see https://github.com/nim-lang/Nim/pull/8584#pullrequestreview-144723468
|
|
||||||
# NOTE: `[].mapIt(it)` is illegal, just as `let a = @[]` is (lacks type
|
|
||||||
# of elements)
|
|
||||||
doAssert: not compiles(mapIt(@[], it))
|
|
||||||
doAssert: not compiles(mapIt([], it))
|
|
||||||
doAssert newSeq[int](0).mapIt(it) == @[]
|
|
||||||
|
|
||||||
block: # mapIt redifinition check, see https://github.com/nim-lang/Nim/issues/8580
|
|
||||||
let s2 = [1, 2].mapIt(it)
|
|
||||||
doAssert s2 == @[1, 2]
|
|
||||||
|
|
||||||
block:
|
|
||||||
counter = 0
|
|
||||||
doAssert [1, 2].identity().mapIt(it*2).mapIt(it*10) == @[20, 40]
|
|
||||||
# https://github.com/nim-lang/Nim/issues/7187 test case
|
|
||||||
doAssert counter == 1
|
|
||||||
|
|
||||||
block: # mapIt with invalid RHS for `let` (#8566)
|
|
||||||
type X = enum
|
|
||||||
A, B
|
|
||||||
doAssert mapIt(X, $it) == @["A", "B"]
|
|
||||||
|
|
||||||
block:
|
|
||||||
# bug #9093
|
|
||||||
let inp = "a:b,c:d"
|
|
||||||
|
|
||||||
let outp = inp.split(",").mapIt(it.split(":"))
|
|
||||||
doAssert outp == @[@["a", "b"], @["c", "d"]]
|
|
||||||
|
|
||||||
|
|
||||||
block:
|
|
||||||
proc iter(len: int): auto =
|
|
||||||
result = iterator(): int =
|
|
||||||
for i in 0..<len:
|
|
||||||
yield i
|
|
||||||
|
|
||||||
doAssert: iter(3).mapIt(2*it).foldl(a + b) == 6
|
|
||||||
|
|
||||||
when not defined(testing):
|
|
||||||
echo "Finished doc tests"
|
|
||||||
|
|
|
||||||
|
|
@ -969,7 +969,8 @@ template verifyJsonKind(node: JsonNode, kinds: set[JsonNodeKind],
|
||||||
|
|
||||||
when defined(nimFixedForwardGeneric):
|
when defined(nimFixedForwardGeneric):
|
||||||
|
|
||||||
macro isRefSkipDistinct(arg: typed): untyped =
|
macro isRefSkipDistinct*(arg: typed): untyped =
|
||||||
|
## internal only, do not use
|
||||||
var impl = getTypeImpl(arg)
|
var impl = getTypeImpl(arg)
|
||||||
if impl.kind == nnkBracketExpr and impl[0].eqIdent("typeDesc"):
|
if impl.kind == nnkBracketExpr and impl[0].eqIdent("typeDesc"):
|
||||||
impl = getTypeImpl(impl[1])
|
impl = getTypeImpl(impl[1])
|
||||||
|
|
@ -1286,235 +1287,3 @@ when false:
|
||||||
|
|
||||||
# { "json": 5 }
|
# { "json": 5 }
|
||||||
# To get that we shall use, obj["json"]
|
# To get that we shall use, obj["json"]
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
# Note: Macro tests are in tests/stdlib/tjsonmacro.nim
|
|
||||||
|
|
||||||
let testJson = parseJson"""{ "a": [1, 2, 3, 4], "b": "asd", "c": "\ud83c\udf83", "d": "\u00E6"}"""
|
|
||||||
# nil passthrough
|
|
||||||
doAssert(testJson{"doesnt_exist"}{"anything"}.isNil)
|
|
||||||
testJson{["e", "f"]} = %true
|
|
||||||
doAssert(testJson["e"]["f"].bval)
|
|
||||||
|
|
||||||
# make sure UTF-16 decoding works.
|
|
||||||
doAssert(testJson["c"].str == "🎃")
|
|
||||||
doAssert(testJson["d"].str == "æ")
|
|
||||||
|
|
||||||
# make sure no memory leek when parsing invalid string
|
|
||||||
let startMemory = getOccupiedMem()
|
|
||||||
for i in 0 .. 10000:
|
|
||||||
try:
|
|
||||||
discard parseJson"""{ invalid"""
|
|
||||||
except:
|
|
||||||
discard
|
|
||||||
# memory diff should less than 4M
|
|
||||||
doAssert(abs(getOccupiedMem() - startMemory) < 4 * 1024 * 1024)
|
|
||||||
|
|
||||||
|
|
||||||
# test `$`
|
|
||||||
let stringified = $testJson
|
|
||||||
let parsedAgain = parseJson(stringified)
|
|
||||||
doAssert(parsedAgain["b"].str == "asd")
|
|
||||||
|
|
||||||
parsedAgain["abc"] = %5
|
|
||||||
doAssert parsedAgain["abc"].num == 5
|
|
||||||
|
|
||||||
# Bounds checking
|
|
||||||
when compileOption("boundChecks"):
|
|
||||||
try:
|
|
||||||
let a = testJson["a"][9]
|
|
||||||
doAssert(false, "IndexDefect not thrown")
|
|
||||||
except IndexDefect:
|
|
||||||
discard
|
|
||||||
try:
|
|
||||||
let a = testJson["a"][-1]
|
|
||||||
doAssert(false, "IndexDefect not thrown")
|
|
||||||
except IndexDefect:
|
|
||||||
discard
|
|
||||||
try:
|
|
||||||
doAssert(testJson["a"][0].num == 1, "Index doesn't correspond to its value")
|
|
||||||
except:
|
|
||||||
doAssert(false, "IndexDefect thrown for valid index")
|
|
||||||
|
|
||||||
doAssert(testJson{"b"}.getStr() == "asd", "Couldn't fetch a singly nested key with {}")
|
|
||||||
doAssert(isNil(testJson{"nonexistent"}), "Non-existent keys should return nil")
|
|
||||||
doAssert(isNil(testJson{"a", "b"}), "Indexing through a list should return nil")
|
|
||||||
doAssert(isNil(testJson{"a", "b"}), "Indexing through a list should return nil")
|
|
||||||
doAssert(testJson{"a"} == parseJson"[1, 2, 3, 4]", "Didn't return a non-JObject when there was one to be found")
|
|
||||||
doAssert(isNil(parseJson("[1, 2, 3]"){"foo"}), "Indexing directly into a list should return nil")
|
|
||||||
|
|
||||||
# Generator:
|
|
||||||
var j = %* [{"name": "John", "age": 30}, {"name": "Susan", "age": 31}]
|
|
||||||
doAssert j == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
|
|
||||||
|
|
||||||
var j2 = %*
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"name": "John",
|
|
||||||
"age": 30
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Susan",
|
|
||||||
"age": 31
|
|
||||||
}
|
|
||||||
]
|
|
||||||
doAssert j2 == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
|
|
||||||
|
|
||||||
var name = "John"
|
|
||||||
let herAge = 30
|
|
||||||
const hisAge = 31
|
|
||||||
|
|
||||||
var j3 = %*
|
|
||||||
[ {"name": "John"
|
|
||||||
, "age": herAge
|
|
||||||
}
|
|
||||||
, {"name": "Susan"
|
|
||||||
, "age": hisAge
|
|
||||||
}
|
|
||||||
]
|
|
||||||
doAssert j3 == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
|
|
||||||
|
|
||||||
var j4 = %*{"test": nil}
|
|
||||||
doAssert j4 == %{"test": newJNull()}
|
|
||||||
|
|
||||||
let seqOfNodes = @[%1, %2]
|
|
||||||
let jSeqOfNodes = %seqOfNodes
|
|
||||||
doAssert(jSeqOfNodes[1].num == 2)
|
|
||||||
|
|
||||||
type MyObj = object
|
|
||||||
a, b: int
|
|
||||||
s: string
|
|
||||||
f32: float32
|
|
||||||
f64: float64
|
|
||||||
next: ref MyObj
|
|
||||||
var m: MyObj
|
|
||||||
m.s = "hi"
|
|
||||||
m.a = 5
|
|
||||||
let jMyObj = %m
|
|
||||||
doAssert(jMyObj["a"].num == 5)
|
|
||||||
doAssert(jMyObj["s"].str == "hi")
|
|
||||||
|
|
||||||
# Test loading of file.
|
|
||||||
when not defined(js):
|
|
||||||
var parsed = parseFile("tests/testdata/jsontest.json")
|
|
||||||
|
|
||||||
try:
|
|
||||||
discard parsed["key2"][12123]
|
|
||||||
doAssert(false)
|
|
||||||
except IndexDefect: doAssert(true)
|
|
||||||
|
|
||||||
var parsed2 = parseFile("tests/testdata/jsontest2.json")
|
|
||||||
doAssert(parsed2{"repository", "description"}.str ==
|
|
||||||
"IRC Library for Haskell", "Couldn't fetch via multiply nested key using {}")
|
|
||||||
|
|
||||||
doAssert escapeJsonUnquoted("\10Foo🎃barÄ") == "\\nFoo🎃barÄ"
|
|
||||||
doAssert escapeJsonUnquoted("\0\7\20") == "\\u0000\\u0007\\u0014" # for #7887
|
|
||||||
doAssert escapeJson("\10Foo🎃barÄ") == "\"\\nFoo🎃barÄ\""
|
|
||||||
doAssert escapeJson("\0\7\20") == "\"\\u0000\\u0007\\u0014\"" # for #7887
|
|
||||||
|
|
||||||
# Test with extra data
|
|
||||||
when not defined(js):
|
|
||||||
try:
|
|
||||||
discard parseJson("123 456")
|
|
||||||
doAssert(false)
|
|
||||||
except JsonParsingError:
|
|
||||||
doAssert getCurrentExceptionMsg().contains(errorMessages[errEofExpected])
|
|
||||||
|
|
||||||
try:
|
|
||||||
discard parseFile("tests/testdata/jsonwithextradata.json")
|
|
||||||
doAssert(false)
|
|
||||||
except JsonParsingError:
|
|
||||||
doAssert getCurrentExceptionMsg().contains(errorMessages[errEofExpected])
|
|
||||||
|
|
||||||
# bug #6438
|
|
||||||
doAssert($ %*[] == "[]")
|
|
||||||
doAssert($ %*{} == "{}")
|
|
||||||
|
|
||||||
doAssert(not compiles(%{"error": "No messages"}))
|
|
||||||
|
|
||||||
# bug #9111
|
|
||||||
block:
|
|
||||||
type
|
|
||||||
Bar = string
|
|
||||||
Foo = object
|
|
||||||
a: int
|
|
||||||
b: Bar
|
|
||||||
|
|
||||||
let
|
|
||||||
js = """{"a": 123, "b": "abc"}""".parseJson
|
|
||||||
foo = js.to Foo
|
|
||||||
|
|
||||||
doAssert(foo.b == "abc")
|
|
||||||
|
|
||||||
# Generate constructors for range[T] types
|
|
||||||
block:
|
|
||||||
type
|
|
||||||
Q1 = range[0'u8 .. 50'u8]
|
|
||||||
Q2 = range[0'u16 .. 50'u16]
|
|
||||||
Q3 = range[0'u32 .. 50'u32]
|
|
||||||
Q4 = range[0'i8 .. 50'i8]
|
|
||||||
Q5 = range[0'i16 .. 50'i16]
|
|
||||||
Q6 = range[0'i32 .. 50'i32]
|
|
||||||
Q7 = range[0'f32 .. 50'f32]
|
|
||||||
Q8 = range[0'f64 .. 50'f64]
|
|
||||||
Q9 = range[0 .. 50]
|
|
||||||
|
|
||||||
X = object
|
|
||||||
m1: Q1
|
|
||||||
m2: Q2
|
|
||||||
m3: Q3
|
|
||||||
m4: Q4
|
|
||||||
m5: Q5
|
|
||||||
m6: Q6
|
|
||||||
m7: Q7
|
|
||||||
m8: Q8
|
|
||||||
m9: Q9
|
|
||||||
|
|
||||||
let obj = X(
|
|
||||||
m1: Q1(42),
|
|
||||||
m2: Q2(42),
|
|
||||||
m3: Q3(42),
|
|
||||||
m4: Q4(42),
|
|
||||||
m5: Q5(42),
|
|
||||||
m6: Q6(42),
|
|
||||||
m7: Q7(42),
|
|
||||||
m8: Q8(42),
|
|
||||||
m9: Q9(42)
|
|
||||||
)
|
|
||||||
|
|
||||||
doAssert(obj == to(%obj, type(obj)))
|
|
||||||
|
|
||||||
when not defined(js):
|
|
||||||
const fragments = """[1,2,3] {"hi":3} 12 [] """
|
|
||||||
var res = ""
|
|
||||||
for x in parseJsonFragments(newStringStream(fragments)):
|
|
||||||
res.add($x)
|
|
||||||
res.add " "
|
|
||||||
doAssert res == fragments
|
|
||||||
|
|
||||||
|
|
||||||
# test isRefSkipDistinct
|
|
||||||
type
|
|
||||||
MyRef = ref object
|
|
||||||
MyObject = object
|
|
||||||
MyDistinct = distinct MyRef
|
|
||||||
MyOtherDistinct = distinct MyRef
|
|
||||||
|
|
||||||
var x0: ref int
|
|
||||||
var x1: MyRef
|
|
||||||
var x2: MyObject
|
|
||||||
var x3: MyDistinct
|
|
||||||
var x4: MyOtherDistinct
|
|
||||||
|
|
||||||
doAssert isRefSkipDistinct(x0)
|
|
||||||
doAssert isRefSkipDistinct(x1)
|
|
||||||
doAssert not isRefSkipDistinct(x2)
|
|
||||||
doAssert isRefSkipDistinct(x3)
|
|
||||||
doAssert isRefSkipDistinct(x4)
|
|
||||||
|
|
||||||
|
|
||||||
doAssert isRefSkipDistinct(ref int)
|
|
||||||
doAssert isRefSkipDistinct(MyRef)
|
|
||||||
doAssert not isRefSkipDistinct(MyObject)
|
|
||||||
doAssert isRefSkipDistinct(MyDistinct)
|
|
||||||
doAssert isRefSkipDistinct(MyOtherDistinct)
|
|
||||||
|
|
|
||||||
|
|
@ -3284,66 +3284,3 @@ func isValidFilename*(filename: string, maxLen = 259.Positive): bool {.since: (1
|
||||||
find(f.name, invalidFilenameChars) != -1): return false
|
find(f.name, invalidFilenameChars) != -1): return false
|
||||||
for invalid in invalidFilenames:
|
for invalid in invalidFilenames:
|
||||||
if cmpIgnoreCase(f.name, invalid) == 0: return false
|
if cmpIgnoreCase(f.name, invalid) == 0: return false
|
||||||
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
assert quoteShellWindows("aaa") == "aaa"
|
|
||||||
assert quoteShellWindows("aaa\"") == "aaa\\\""
|
|
||||||
assert quoteShellWindows("") == "\"\""
|
|
||||||
|
|
||||||
assert quoteShellPosix("aaa") == "aaa"
|
|
||||||
assert quoteShellPosix("aaa a") == "'aaa a'"
|
|
||||||
assert quoteShellPosix("") == "''"
|
|
||||||
assert quoteShellPosix("a'a") == "'a'\"'\"'a'"
|
|
||||||
|
|
||||||
when defined(posix):
|
|
||||||
assert quoteShell("") == "''"
|
|
||||||
|
|
||||||
block normalizePathEndTest:
|
|
||||||
# handle edge cases correctly: shouldn't affect whether path is
|
|
||||||
# absolute/relative
|
|
||||||
doAssert "".normalizePathEnd(true) == ""
|
|
||||||
doAssert "".normalizePathEnd(false) == ""
|
|
||||||
doAssert "/".normalizePathEnd(true) == $DirSep
|
|
||||||
doAssert "/".normalizePathEnd(false) == $DirSep
|
|
||||||
|
|
||||||
when defined(posix):
|
|
||||||
doAssert "//".normalizePathEnd(false) == "/"
|
|
||||||
doAssert "foo.bar//".normalizePathEnd == "foo.bar"
|
|
||||||
doAssert "bar//".normalizePathEnd(trailingSep = true) == "bar/"
|
|
||||||
when defined(Windows):
|
|
||||||
doAssert r"C:\foo\\".normalizePathEnd == r"C:\foo"
|
|
||||||
doAssert r"C:\foo".normalizePathEnd(trailingSep = true) == r"C:\foo\"
|
|
||||||
# this one is controversial: we could argue for returning `D:\` instead,
|
|
||||||
# but this is simplest.
|
|
||||||
doAssert r"D:\".normalizePathEnd == r"D:"
|
|
||||||
doAssert r"E:/".normalizePathEnd(trailingSep = true) == r"E:\"
|
|
||||||
doAssert "/".normalizePathEnd == r"\"
|
|
||||||
|
|
||||||
|
|
||||||
block isValidFilenameTest:
|
|
||||||
# Negative Tests.
|
|
||||||
doAssert not isValidFilename("abcd", maxLen = 2)
|
|
||||||
doAssert not isValidFilename("0123456789", maxLen = 8)
|
|
||||||
doAssert not isValidFilename("con")
|
|
||||||
doAssert not isValidFilename("aux")
|
|
||||||
doAssert not isValidFilename("prn")
|
|
||||||
doAssert not isValidFilename("OwO|UwU")
|
|
||||||
doAssert not isValidFilename(" foo")
|
|
||||||
doAssert not isValidFilename("foo ")
|
|
||||||
doAssert not isValidFilename("foo.")
|
|
||||||
doAssert not isValidFilename("con.txt")
|
|
||||||
doAssert not isValidFilename("aux.bat")
|
|
||||||
doAssert not isValidFilename("prn.exe")
|
|
||||||
doAssert not isValidFilename("nim>.nim")
|
|
||||||
doAssert not isValidFilename(" foo.log")
|
|
||||||
# Positive Tests.
|
|
||||||
doAssert isValidFilename("abcd", maxLen = 42.Positive)
|
|
||||||
doAssert isValidFilename("c0n")
|
|
||||||
doAssert isValidFilename("foo.aux")
|
|
||||||
doAssert isValidFilename("bar.prn")
|
|
||||||
doAssert isValidFilename("OwO_UwU")
|
|
||||||
doAssert isValidFilename("cron")
|
|
||||||
doAssert isValidFilename("ux.bat")
|
|
||||||
doAssert isValidFilename("nim.nim")
|
|
||||||
doAssert isValidFilename("foo.log")
|
|
||||||
|
|
|
||||||
234
tests/stdlib/tjson.nim
Normal file
234
tests/stdlib/tjson.nim
Normal file
|
|
@ -0,0 +1,234 @@
|
||||||
|
#[
|
||||||
|
Note: Macro tests are in tests/stdlib/tjsonmacro.nim
|
||||||
|
]#
|
||||||
|
|
||||||
|
import std/[json,parsejson,strutils,streams]
|
||||||
|
|
||||||
|
let testJson = parseJson"""{ "a": [1, 2, 3, 4], "b": "asd", "c": "\ud83c\udf83", "d": "\u00E6"}"""
|
||||||
|
# nil passthrough
|
||||||
|
doAssert(testJson{"doesnt_exist"}{"anything"}.isNil)
|
||||||
|
testJson{["e", "f"]} = %true
|
||||||
|
doAssert(testJson["e"]["f"].bval)
|
||||||
|
|
||||||
|
# make sure UTF-16 decoding works.
|
||||||
|
doAssert(testJson["c"].str == "🎃")
|
||||||
|
doAssert(testJson["d"].str == "æ")
|
||||||
|
|
||||||
|
# make sure no memory leek when parsing invalid string
|
||||||
|
let startMemory = getOccupiedMem()
|
||||||
|
for i in 0 .. 10000:
|
||||||
|
try:
|
||||||
|
discard parseJson"""{ invalid"""
|
||||||
|
except:
|
||||||
|
discard
|
||||||
|
# memory diff should less than 4M
|
||||||
|
doAssert(abs(getOccupiedMem() - startMemory) < 4 * 1024 * 1024)
|
||||||
|
|
||||||
|
|
||||||
|
# test `$`
|
||||||
|
let stringified = $testJson
|
||||||
|
let parsedAgain = parseJson(stringified)
|
||||||
|
doAssert(parsedAgain["b"].str == "asd")
|
||||||
|
|
||||||
|
parsedAgain["abc"] = %5
|
||||||
|
doAssert parsedAgain["abc"].num == 5
|
||||||
|
|
||||||
|
# Bounds checking
|
||||||
|
when compileOption("boundChecks"):
|
||||||
|
try:
|
||||||
|
let a = testJson["a"][9]
|
||||||
|
doAssert(false, "IndexDefect not thrown")
|
||||||
|
except IndexDefect:
|
||||||
|
discard
|
||||||
|
try:
|
||||||
|
let a = testJson["a"][-1]
|
||||||
|
doAssert(false, "IndexDefect not thrown")
|
||||||
|
except IndexDefect:
|
||||||
|
discard
|
||||||
|
try:
|
||||||
|
doAssert(testJson["a"][0].num == 1, "Index doesn't correspond to its value")
|
||||||
|
except:
|
||||||
|
doAssert(false, "IndexDefect thrown for valid index")
|
||||||
|
|
||||||
|
doAssert(testJson{"b"}.getStr() == "asd", "Couldn't fetch a singly nested key with {}")
|
||||||
|
doAssert(isNil(testJson{"nonexistent"}), "Non-existent keys should return nil")
|
||||||
|
doAssert(isNil(testJson{"a", "b"}), "Indexing through a list should return nil")
|
||||||
|
doAssert(isNil(testJson{"a", "b"}), "Indexing through a list should return nil")
|
||||||
|
doAssert(testJson{"a"} == parseJson"[1, 2, 3, 4]", "Didn't return a non-JObject when there was one to be found")
|
||||||
|
doAssert(isNil(parseJson("[1, 2, 3]"){"foo"}), "Indexing directly into a list should return nil")
|
||||||
|
|
||||||
|
# Generator:
|
||||||
|
var j = %* [{"name": "John", "age": 30}, {"name": "Susan", "age": 31}]
|
||||||
|
doAssert j == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
|
||||||
|
|
||||||
|
var j2 = %*
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "John",
|
||||||
|
"age": 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Susan",
|
||||||
|
"age": 31
|
||||||
|
}
|
||||||
|
]
|
||||||
|
doAssert j2 == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
|
||||||
|
|
||||||
|
var name = "John"
|
||||||
|
let herAge = 30
|
||||||
|
const hisAge = 31
|
||||||
|
|
||||||
|
var j3 = %*
|
||||||
|
[ {"name": "John"
|
||||||
|
, "age": herAge
|
||||||
|
}
|
||||||
|
, {"name": "Susan"
|
||||||
|
, "age": hisAge
|
||||||
|
}
|
||||||
|
]
|
||||||
|
doAssert j3 == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
|
||||||
|
|
||||||
|
var j4 = %*{"test": nil}
|
||||||
|
doAssert j4 == %{"test": newJNull()}
|
||||||
|
|
||||||
|
let seqOfNodes = @[%1, %2]
|
||||||
|
let jSeqOfNodes = %seqOfNodes
|
||||||
|
doAssert(jSeqOfNodes[1].num == 2)
|
||||||
|
|
||||||
|
type MyObj = object
|
||||||
|
a, b: int
|
||||||
|
s: string
|
||||||
|
f32: float32
|
||||||
|
f64: float64
|
||||||
|
next: ref MyObj
|
||||||
|
var m: MyObj
|
||||||
|
m.s = "hi"
|
||||||
|
m.a = 5
|
||||||
|
let jMyObj = %m
|
||||||
|
doAssert(jMyObj["a"].num == 5)
|
||||||
|
doAssert(jMyObj["s"].str == "hi")
|
||||||
|
|
||||||
|
# Test loading of file.
|
||||||
|
when not defined(js):
|
||||||
|
var parsed = parseFile("tests/testdata/jsontest.json")
|
||||||
|
|
||||||
|
try:
|
||||||
|
discard parsed["key2"][12123]
|
||||||
|
doAssert(false)
|
||||||
|
except IndexDefect: doAssert(true)
|
||||||
|
|
||||||
|
var parsed2 = parseFile("tests/testdata/jsontest2.json")
|
||||||
|
doAssert(parsed2{"repository", "description"}.str ==
|
||||||
|
"IRC Library for Haskell", "Couldn't fetch via multiply nested key using {}")
|
||||||
|
|
||||||
|
doAssert escapeJsonUnquoted("\10Foo🎃barÄ") == "\\nFoo🎃barÄ"
|
||||||
|
doAssert escapeJsonUnquoted("\0\7\20") == "\\u0000\\u0007\\u0014" # for #7887
|
||||||
|
doAssert escapeJson("\10Foo🎃barÄ") == "\"\\nFoo🎃barÄ\""
|
||||||
|
doAssert escapeJson("\0\7\20") == "\"\\u0000\\u0007\\u0014\"" # for #7887
|
||||||
|
|
||||||
|
# Test with extra data
|
||||||
|
when not defined(js):
|
||||||
|
try:
|
||||||
|
discard parseJson("123 456")
|
||||||
|
doAssert(false)
|
||||||
|
except JsonParsingError:
|
||||||
|
doAssert getCurrentExceptionMsg().contains(errorMessages[errEofExpected])
|
||||||
|
|
||||||
|
try:
|
||||||
|
discard parseFile("tests/testdata/jsonwithextradata.json")
|
||||||
|
doAssert(false)
|
||||||
|
except JsonParsingError:
|
||||||
|
doAssert getCurrentExceptionMsg().contains(errorMessages[errEofExpected])
|
||||||
|
|
||||||
|
# bug #6438
|
||||||
|
doAssert($ %*[] == "[]")
|
||||||
|
doAssert($ %*{} == "{}")
|
||||||
|
|
||||||
|
doAssert(not compiles(%{"error": "No messages"}))
|
||||||
|
|
||||||
|
# bug #9111
|
||||||
|
block:
|
||||||
|
type
|
||||||
|
Bar = string
|
||||||
|
Foo = object
|
||||||
|
a: int
|
||||||
|
b: Bar
|
||||||
|
|
||||||
|
let
|
||||||
|
js = """{"a": 123, "b": "abc"}""".parseJson
|
||||||
|
foo = js.to Foo
|
||||||
|
|
||||||
|
doAssert(foo.b == "abc")
|
||||||
|
|
||||||
|
# Generate constructors for range[T] types
|
||||||
|
block:
|
||||||
|
type
|
||||||
|
Q1 = range[0'u8 .. 50'u8]
|
||||||
|
Q2 = range[0'u16 .. 50'u16]
|
||||||
|
Q3 = range[0'u32 .. 50'u32]
|
||||||
|
Q4 = range[0'i8 .. 50'i8]
|
||||||
|
Q5 = range[0'i16 .. 50'i16]
|
||||||
|
Q6 = range[0'i32 .. 50'i32]
|
||||||
|
Q7 = range[0'f32 .. 50'f32]
|
||||||
|
Q8 = range[0'f64 .. 50'f64]
|
||||||
|
Q9 = range[0 .. 50]
|
||||||
|
|
||||||
|
X = object
|
||||||
|
m1: Q1
|
||||||
|
m2: Q2
|
||||||
|
m3: Q3
|
||||||
|
m4: Q4
|
||||||
|
m5: Q5
|
||||||
|
m6: Q6
|
||||||
|
m7: Q7
|
||||||
|
m8: Q8
|
||||||
|
m9: Q9
|
||||||
|
|
||||||
|
let obj = X(
|
||||||
|
m1: Q1(42),
|
||||||
|
m2: Q2(42),
|
||||||
|
m3: Q3(42),
|
||||||
|
m4: Q4(42),
|
||||||
|
m5: Q5(42),
|
||||||
|
m6: Q6(42),
|
||||||
|
m7: Q7(42),
|
||||||
|
m8: Q8(42),
|
||||||
|
m9: Q9(42)
|
||||||
|
)
|
||||||
|
|
||||||
|
doAssert(obj == to(%obj, type(obj)))
|
||||||
|
|
||||||
|
when not defined(js):
|
||||||
|
const fragments = """[1,2,3] {"hi":3} 12 [] """
|
||||||
|
var res = ""
|
||||||
|
for x in parseJsonFragments(newStringStream(fragments)):
|
||||||
|
res.add($x)
|
||||||
|
res.add " "
|
||||||
|
doAssert res == fragments
|
||||||
|
|
||||||
|
|
||||||
|
# test isRefSkipDistinct
|
||||||
|
type
|
||||||
|
MyRef = ref object
|
||||||
|
MyObject = object
|
||||||
|
MyDistinct = distinct MyRef
|
||||||
|
MyOtherDistinct = distinct MyRef
|
||||||
|
|
||||||
|
var x0: ref int
|
||||||
|
var x1: MyRef
|
||||||
|
var x2: MyObject
|
||||||
|
var x3: MyDistinct
|
||||||
|
var x4: MyOtherDistinct
|
||||||
|
|
||||||
|
doAssert isRefSkipDistinct(x0)
|
||||||
|
doAssert isRefSkipDistinct(x1)
|
||||||
|
doAssert not isRefSkipDistinct(x2)
|
||||||
|
doAssert isRefSkipDistinct(x3)
|
||||||
|
doAssert isRefSkipDistinct(x4)
|
||||||
|
|
||||||
|
|
||||||
|
doAssert isRefSkipDistinct(ref int)
|
||||||
|
doAssert isRefSkipDistinct(MyRef)
|
||||||
|
doAssert not isRefSkipDistinct(MyObject)
|
||||||
|
doAssert isRefSkipDistinct(MyDistinct)
|
||||||
|
doAssert isRefSkipDistinct(MyOtherDistinct)
|
||||||
|
|
@ -447,3 +447,66 @@ block isRelativeTo:
|
||||||
doAssert isRelativeTo("foo/bar", ".")
|
doAssert isRelativeTo("foo/bar", ".")
|
||||||
doAssert not isRelativeTo("foo/bar.nims", "foo/bar.nim")
|
doAssert not isRelativeTo("foo/bar.nims", "foo/bar.nim")
|
||||||
doAssert not isRelativeTo("/foo2", "/foo")
|
doAssert not isRelativeTo("/foo2", "/foo")
|
||||||
|
|
||||||
|
block: # quoteShellWindows
|
||||||
|
assert quoteShellWindows("aaa") == "aaa"
|
||||||
|
assert quoteShellWindows("aaa\"") == "aaa\\\""
|
||||||
|
assert quoteShellWindows("") == "\"\""
|
||||||
|
|
||||||
|
block: # quoteShellWindows
|
||||||
|
assert quoteShellPosix("aaa") == "aaa"
|
||||||
|
assert quoteShellPosix("aaa a") == "'aaa a'"
|
||||||
|
assert quoteShellPosix("") == "''"
|
||||||
|
assert quoteShellPosix("a'a") == "'a'\"'\"'a'"
|
||||||
|
|
||||||
|
block: # quoteShell
|
||||||
|
when defined(posix):
|
||||||
|
assert quoteShell("") == "''"
|
||||||
|
|
||||||
|
block: # normalizePathEnd
|
||||||
|
# handle edge cases correctly: shouldn't affect whether path is
|
||||||
|
# absolute/relative
|
||||||
|
doAssert "".normalizePathEnd(true) == ""
|
||||||
|
doAssert "".normalizePathEnd(false) == ""
|
||||||
|
doAssert "/".normalizePathEnd(true) == $DirSep
|
||||||
|
doAssert "/".normalizePathEnd(false) == $DirSep
|
||||||
|
|
||||||
|
when defined(posix):
|
||||||
|
doAssert "//".normalizePathEnd(false) == "/"
|
||||||
|
doAssert "foo.bar//".normalizePathEnd == "foo.bar"
|
||||||
|
doAssert "bar//".normalizePathEnd(trailingSep = true) == "bar/"
|
||||||
|
when defined(Windows):
|
||||||
|
doAssert r"C:\foo\\".normalizePathEnd == r"C:\foo"
|
||||||
|
doAssert r"C:\foo".normalizePathEnd(trailingSep = true) == r"C:\foo\"
|
||||||
|
# this one is controversial: we could argue for returning `D:\` instead,
|
||||||
|
# but this is simplest.
|
||||||
|
doAssert r"D:\".normalizePathEnd == r"D:"
|
||||||
|
doAssert r"E:/".normalizePathEnd(trailingSep = true) == r"E:\"
|
||||||
|
doAssert "/".normalizePathEnd == r"\"
|
||||||
|
|
||||||
|
block: # isValidFilename
|
||||||
|
# Negative Tests.
|
||||||
|
doAssert not isValidFilename("abcd", maxLen = 2)
|
||||||
|
doAssert not isValidFilename("0123456789", maxLen = 8)
|
||||||
|
doAssert not isValidFilename("con")
|
||||||
|
doAssert not isValidFilename("aux")
|
||||||
|
doAssert not isValidFilename("prn")
|
||||||
|
doAssert not isValidFilename("OwO|UwU")
|
||||||
|
doAssert not isValidFilename(" foo")
|
||||||
|
doAssert not isValidFilename("foo ")
|
||||||
|
doAssert not isValidFilename("foo.")
|
||||||
|
doAssert not isValidFilename("con.txt")
|
||||||
|
doAssert not isValidFilename("aux.bat")
|
||||||
|
doAssert not isValidFilename("prn.exe")
|
||||||
|
doAssert not isValidFilename("nim>.nim")
|
||||||
|
doAssert not isValidFilename(" foo.log")
|
||||||
|
# Positive Tests.
|
||||||
|
doAssert isValidFilename("abcd", maxLen = 42.Positive)
|
||||||
|
doAssert isValidFilename("c0n")
|
||||||
|
doAssert isValidFilename("foo.aux")
|
||||||
|
doAssert isValidFilename("bar.prn")
|
||||||
|
doAssert isValidFilename("OwO_UwU")
|
||||||
|
doAssert isValidFilename("cron")
|
||||||
|
doAssert isValidFilename("ux.bat")
|
||||||
|
doAssert isValidFilename("nim.nim")
|
||||||
|
doAssert isValidFilename("foo.log")
|
||||||
|
|
|
||||||
460
tests/stdlib/tsequtils.nim
Normal file
460
tests/stdlib/tsequtils.nim
Normal file
|
|
@ -0,0 +1,460 @@
|
||||||
|
import std/sequtils
|
||||||
|
import strutils
|
||||||
|
from algorithm import sorted
|
||||||
|
|
||||||
|
# helper for testing double substitution side effects which are handled
|
||||||
|
# by `evalOnceAs`
|
||||||
|
var counter = 0
|
||||||
|
proc identity[T](a: T): auto =
|
||||||
|
counter.inc
|
||||||
|
a
|
||||||
|
|
||||||
|
block: # concat test
|
||||||
|
let
|
||||||
|
s1 = @[1, 2, 3]
|
||||||
|
s2 = @[4, 5]
|
||||||
|
s3 = @[6, 7]
|
||||||
|
total = concat(s1, s2, s3)
|
||||||
|
assert total == @[1, 2, 3, 4, 5, 6, 7]
|
||||||
|
|
||||||
|
block: # count test
|
||||||
|
let
|
||||||
|
s1 = @[1, 2, 3, 2]
|
||||||
|
s2 = @['a', 'b', 'x', 'a']
|
||||||
|
a1 = [1, 2, 3, 2]
|
||||||
|
a2 = ['a', 'b', 'x', 'a']
|
||||||
|
r0 = count(s1, 0)
|
||||||
|
r1 = count(s1, 1)
|
||||||
|
r2 = count(s1, 2)
|
||||||
|
r3 = count(s2, 'y')
|
||||||
|
r4 = count(s2, 'x')
|
||||||
|
r5 = count(s2, 'a')
|
||||||
|
ar0 = count(a1, 0)
|
||||||
|
ar1 = count(a1, 1)
|
||||||
|
ar2 = count(a1, 2)
|
||||||
|
ar3 = count(a2, 'y')
|
||||||
|
ar4 = count(a2, 'x')
|
||||||
|
ar5 = count(a2, 'a')
|
||||||
|
assert r0 == 0
|
||||||
|
assert r1 == 1
|
||||||
|
assert r2 == 2
|
||||||
|
assert r3 == 0
|
||||||
|
assert r4 == 1
|
||||||
|
assert r5 == 2
|
||||||
|
assert ar0 == 0
|
||||||
|
assert ar1 == 1
|
||||||
|
assert ar2 == 2
|
||||||
|
assert ar3 == 0
|
||||||
|
assert ar4 == 1
|
||||||
|
assert ar5 == 2
|
||||||
|
|
||||||
|
block: # cycle tests
|
||||||
|
let
|
||||||
|
a = @[1, 2, 3]
|
||||||
|
b: seq[int] = @[]
|
||||||
|
c = [1, 2, 3]
|
||||||
|
|
||||||
|
doAssert a.cycle(3) == @[1, 2, 3, 1, 2, 3, 1, 2, 3]
|
||||||
|
doAssert a.cycle(0) == @[]
|
||||||
|
#doAssert a.cycle(-1) == @[] # will not compile!
|
||||||
|
doAssert b.cycle(3) == @[]
|
||||||
|
doAssert c.cycle(3) == @[1, 2, 3, 1, 2, 3, 1, 2, 3]
|
||||||
|
doAssert c.cycle(0) == @[]
|
||||||
|
|
||||||
|
block: # repeat tests
|
||||||
|
assert repeat(10, 5) == @[10, 10, 10, 10, 10]
|
||||||
|
assert repeat(@[1, 2, 3], 2) == @[@[1, 2, 3], @[1, 2, 3]]
|
||||||
|
assert repeat([1, 2, 3], 2) == @[[1, 2, 3], [1, 2, 3]]
|
||||||
|
|
||||||
|
block: # deduplicates test
|
||||||
|
let
|
||||||
|
dup1 = @[1, 1, 3, 4, 2, 2, 8, 1, 4]
|
||||||
|
dup2 = @["a", "a", "c", "d", "d"]
|
||||||
|
dup3 = [1, 1, 3, 4, 2, 2, 8, 1, 4]
|
||||||
|
dup4 = ["a", "a", "c", "d", "d"]
|
||||||
|
unique1 = deduplicate(dup1)
|
||||||
|
unique2 = deduplicate(dup2)
|
||||||
|
unique3 = deduplicate(dup3)
|
||||||
|
unique4 = deduplicate(dup4)
|
||||||
|
unique5 = deduplicate(dup1.sorted, true)
|
||||||
|
unique6 = deduplicate(dup2, true)
|
||||||
|
unique7 = deduplicate(dup3.sorted, true)
|
||||||
|
unique8 = deduplicate(dup4, true)
|
||||||
|
assert unique1 == @[1, 3, 4, 2, 8]
|
||||||
|
assert unique2 == @["a", "c", "d"]
|
||||||
|
assert unique3 == @[1, 3, 4, 2, 8]
|
||||||
|
assert unique4 == @["a", "c", "d"]
|
||||||
|
assert unique5 == @[1, 2, 3, 4, 8]
|
||||||
|
assert unique6 == @["a", "c", "d"]
|
||||||
|
assert unique7 == @[1, 2, 3, 4, 8]
|
||||||
|
assert unique8 == @["a", "c", "d"]
|
||||||
|
|
||||||
|
block: # zip test
|
||||||
|
let
|
||||||
|
short = @[1, 2, 3]
|
||||||
|
long = @[6, 5, 4, 3, 2, 1]
|
||||||
|
words = @["one", "two", "three"]
|
||||||
|
ashort = [1, 2, 3]
|
||||||
|
along = [6, 5, 4, 3, 2, 1]
|
||||||
|
awords = ["one", "two", "three"]
|
||||||
|
zip1 = zip(short, long)
|
||||||
|
zip2 = zip(short, words)
|
||||||
|
zip3 = zip(ashort, along)
|
||||||
|
assert zip1 == @[(1, 6), (2, 5), (3, 4)]
|
||||||
|
assert zip2 == @[(1, "one"), (2, "two"), (3, "three")]
|
||||||
|
assert zip3 == @[(1, 6), (2, 5), (3, 4)]
|
||||||
|
assert zip1[2][1] == 4
|
||||||
|
assert zip2[2][1] == "three"
|
||||||
|
assert zip3[2][1] == 4
|
||||||
|
when (NimMajor, NimMinor) <= (1, 0):
|
||||||
|
let
|
||||||
|
# In Nim 1.0.x and older, zip returned a seq of tuple strictly
|
||||||
|
# with fields named "a" and "b".
|
||||||
|
zipAb = zip(ashort, awords)
|
||||||
|
assert zipAb == @[(a: 1, b: "one"), (2, "two"), (3, "three")]
|
||||||
|
assert zipAb[2].b == "three"
|
||||||
|
else:
|
||||||
|
let
|
||||||
|
# As zip returns seq of anonymous tuples, they can be assigned
|
||||||
|
# to any variable that's a sequence of named tuples too.
|
||||||
|
zipXy: seq[tuple[x: int, y: string]] = zip(ashort, awords)
|
||||||
|
zipMn: seq[tuple[m: int, n: string]] = zip(ashort, words)
|
||||||
|
assert zipXy == @[(x: 1, y: "one"), (2, "two"), (3, "three")]
|
||||||
|
assert zipMn == @[(m: 1, n: "one"), (2, "two"), (3, "three")]
|
||||||
|
assert zipXy[2].y == "three"
|
||||||
|
assert zipMn[2].n == "three"
|
||||||
|
|
||||||
|
block: # distribute tests
|
||||||
|
let numbers = @[1, 2, 3, 4, 5, 6, 7]
|
||||||
|
doAssert numbers.distribute(3) == @[@[1, 2, 3], @[4, 5], @[6, 7]]
|
||||||
|
doAssert numbers.distribute(6)[0] == @[1, 2]
|
||||||
|
doAssert numbers.distribute(6)[5] == @[7]
|
||||||
|
let a = @[1, 2, 3, 4, 5, 6, 7]
|
||||||
|
doAssert a.distribute(1, true) == @[@[1, 2, 3, 4, 5, 6, 7]]
|
||||||
|
doAssert a.distribute(1, false) == @[@[1, 2, 3, 4, 5, 6, 7]]
|
||||||
|
doAssert a.distribute(2, true) == @[@[1, 2, 3, 4], @[5, 6, 7]]
|
||||||
|
doAssert a.distribute(2, false) == @[@[1, 2, 3, 4], @[5, 6, 7]]
|
||||||
|
doAssert a.distribute(3, true) == @[@[1, 2, 3], @[4, 5], @[6, 7]]
|
||||||
|
doAssert a.distribute(3, false) == @[@[1, 2, 3], @[4, 5, 6], @[7]]
|
||||||
|
doAssert a.distribute(4, true) == @[@[1, 2], @[3, 4], @[5, 6], @[7]]
|
||||||
|
doAssert a.distribute(4, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7]]
|
||||||
|
doAssert a.distribute(5, true) == @[@[1, 2], @[3, 4], @[5], @[6], @[7]]
|
||||||
|
doAssert a.distribute(5, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7], @[]]
|
||||||
|
doAssert a.distribute(6, true) == @[@[1, 2], @[3], @[4], @[5], @[6], @[7]]
|
||||||
|
doAssert a.distribute(6, false) == @[
|
||||||
|
@[1, 2], @[3, 4], @[5, 6], @[7], @[], @[]]
|
||||||
|
doAssert a.distribute(8, false) == a.distribute(8, true)
|
||||||
|
doAssert a.distribute(90, false) == a.distribute(90, true)
|
||||||
|
var b = @[0]
|
||||||
|
for f in 1 .. 25: b.add(f)
|
||||||
|
doAssert b.distribute(5, true)[4].len == 5
|
||||||
|
doAssert b.distribute(5, false)[4].len == 2
|
||||||
|
|
||||||
|
block: # map test
|
||||||
|
let
|
||||||
|
numbers = @[1, 4, 5, 8, 9, 7, 4]
|
||||||
|
anumbers = [1, 4, 5, 8, 9, 7, 4]
|
||||||
|
m1 = map(numbers, proc(x: int): int = 2*x)
|
||||||
|
m2 = map(anumbers, proc(x: int): int = 2*x)
|
||||||
|
assert m1 == @[2, 8, 10, 16, 18, 14, 8]
|
||||||
|
assert m2 == @[2, 8, 10, 16, 18, 14, 8]
|
||||||
|
|
||||||
|
block: # apply test
|
||||||
|
var a = @["1", "2", "3", "4"]
|
||||||
|
apply(a, proc(x: var string) = x &= "42")
|
||||||
|
assert a == @["142", "242", "342", "442"]
|
||||||
|
|
||||||
|
block: # filter proc test
|
||||||
|
let
|
||||||
|
colors = @["red", "yellow", "black"]
|
||||||
|
acolors = ["red", "yellow", "black"]
|
||||||
|
f1 = filter(colors, proc(x: string): bool = x.len < 6)
|
||||||
|
f2 = filter(colors) do (x: string) -> bool: x.len > 5
|
||||||
|
f3 = filter(acolors, proc(x: string): bool = x.len < 6)
|
||||||
|
f4 = filter(acolors) do (x: string) -> bool: x.len > 5
|
||||||
|
assert f1 == @["red", "black"]
|
||||||
|
assert f2 == @["yellow"]
|
||||||
|
assert f3 == @["red", "black"]
|
||||||
|
assert f4 == @["yellow"]
|
||||||
|
|
||||||
|
block: # filter iterator test
|
||||||
|
let numbers = @[1, 4, 5, 8, 9, 7, 4]
|
||||||
|
let anumbers = [1, 4, 5, 8, 9, 7, 4]
|
||||||
|
assert toSeq(filter(numbers, proc (x: int): bool = x mod 2 == 0)) ==
|
||||||
|
@[4, 8, 4]
|
||||||
|
assert toSeq(filter(anumbers, proc (x: int): bool = x mod 2 == 0)) ==
|
||||||
|
@[4, 8, 4]
|
||||||
|
|
||||||
|
block: # keepIf test
|
||||||
|
var floats = @[13.0, 12.5, 5.8, 2.0, 6.1, 9.9, 10.1]
|
||||||
|
keepIf(floats, proc(x: float): bool = x > 10)
|
||||||
|
assert floats == @[13.0, 12.5, 10.1]
|
||||||
|
|
||||||
|
block: # delete tests
|
||||||
|
let outcome = @[1, 1, 1, 1, 1, 1, 1, 1]
|
||||||
|
var dest = @[1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1]
|
||||||
|
dest.delete(3, 8)
|
||||||
|
assert outcome == dest, """\
|
||||||
|
Deleting range 3-9 from [1,1,1,2,2,2,2,2,2,1,1,1,1,1]
|
||||||
|
is [1,1,1,1,1,1,1,1]"""
|
||||||
|
var x = @[1, 2, 3]
|
||||||
|
x.delete(100, 100)
|
||||||
|
assert x == @[1, 2, 3]
|
||||||
|
|
||||||
|
block: # insert tests
|
||||||
|
var dest = @[1, 1, 1, 1, 1, 1, 1, 1]
|
||||||
|
let
|
||||||
|
src = @[2, 2, 2, 2, 2, 2]
|
||||||
|
outcome = @[1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1]
|
||||||
|
dest.insert(src, 3)
|
||||||
|
assert dest == outcome, """\
|
||||||
|
Inserting [2,2,2,2,2,2] into [1,1,1,1,1,1,1,1]
|
||||||
|
at 3 is [1,1,1,2,2,2,2,2,2,1,1,1,1,1]"""
|
||||||
|
|
||||||
|
block: # filterIt test
|
||||||
|
let
|
||||||
|
temperatures = @[-272.15, -2.0, 24.5, 44.31, 99.9, -113.44]
|
||||||
|
acceptable = filterIt(temperatures, it < 50 and it > -10)
|
||||||
|
notAcceptable = filterIt(temperatures, it > 50 or it < -10)
|
||||||
|
assert acceptable == @[-2.0, 24.5, 44.31]
|
||||||
|
assert notAcceptable == @[-272.15, 99.9, -113.44]
|
||||||
|
|
||||||
|
block: # keepItIf test
|
||||||
|
var candidates = @["foo", "bar", "baz", "foobar"]
|
||||||
|
keepItIf(candidates, it.len == 3 and it[0] == 'b')
|
||||||
|
assert candidates == @["bar", "baz"]
|
||||||
|
|
||||||
|
block: # all
|
||||||
|
let
|
||||||
|
numbers = @[1, 4, 5, 8, 9, 7, 4]
|
||||||
|
anumbers = [1, 4, 5, 8, 9, 7, 4]
|
||||||
|
len0seq: seq[int] = @[]
|
||||||
|
assert all(numbers, proc (x: int): bool = return x < 10) == true
|
||||||
|
assert all(numbers, proc (x: int): bool = return x < 9) == false
|
||||||
|
assert all(len0seq, proc (x: int): bool = return false) == true
|
||||||
|
assert all(anumbers, proc (x: int): bool = return x < 10) == true
|
||||||
|
assert all(anumbers, proc (x: int): bool = return x < 9) == false
|
||||||
|
|
||||||
|
block: # allIt
|
||||||
|
let
|
||||||
|
numbers = @[1, 4, 5, 8, 9, 7, 4]
|
||||||
|
anumbers = [1, 4, 5, 8, 9, 7, 4]
|
||||||
|
len0seq: seq[int] = @[]
|
||||||
|
assert allIt(numbers, it < 10) == true
|
||||||
|
assert allIt(numbers, it < 9) == false
|
||||||
|
assert allIt(len0seq, false) == true
|
||||||
|
assert allIt(anumbers, it < 10) == true
|
||||||
|
assert allIt(anumbers, it < 9) == false
|
||||||
|
|
||||||
|
block: # any
|
||||||
|
let
|
||||||
|
numbers = @[1, 4, 5, 8, 9, 7, 4]
|
||||||
|
anumbers = [1, 4, 5, 8, 9, 7, 4]
|
||||||
|
len0seq: seq[int] = @[]
|
||||||
|
assert any(numbers, proc (x: int): bool = return x > 8) == true
|
||||||
|
assert any(numbers, proc (x: int): bool = return x > 9) == false
|
||||||
|
assert any(len0seq, proc (x: int): bool = return true) == false
|
||||||
|
assert any(anumbers, proc (x: int): bool = return x > 8) == true
|
||||||
|
assert any(anumbers, proc (x: int): bool = return x > 9) == false
|
||||||
|
|
||||||
|
block: # anyIt
|
||||||
|
let
|
||||||
|
numbers = @[1, 4, 5, 8, 9, 7, 4]
|
||||||
|
anumbers = [1, 4, 5, 8, 9, 7, 4]
|
||||||
|
len0seq: seq[int] = @[]
|
||||||
|
assert anyIt(numbers, it > 8) == true
|
||||||
|
assert anyIt(numbers, it > 9) == false
|
||||||
|
assert anyIt(len0seq, true) == false
|
||||||
|
assert anyIt(anumbers, it > 8) == true
|
||||||
|
assert anyIt(anumbers, it > 9) == false
|
||||||
|
|
||||||
|
block: # toSeq test
|
||||||
|
block:
|
||||||
|
let
|
||||||
|
numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||||
|
oddNumbers = toSeq(filter(numeric) do (x: int) -> bool:
|
||||||
|
if x mod 2 == 1:
|
||||||
|
result = true)
|
||||||
|
assert oddNumbers == @[1, 3, 5, 7, 9]
|
||||||
|
|
||||||
|
block:
|
||||||
|
doAssert [1, 2].toSeq == @[1, 2]
|
||||||
|
doAssert @[1, 2].toSeq == @[1, 2]
|
||||||
|
|
||||||
|
doAssert @[1, 2].toSeq == @[1, 2]
|
||||||
|
doAssert toSeq(@[1, 2]) == @[1, 2]
|
||||||
|
|
||||||
|
block:
|
||||||
|
iterator myIter(seed: int): auto =
|
||||||
|
for i in 0..<seed:
|
||||||
|
yield i
|
||||||
|
doAssert toSeq(myIter(2)) == @[0, 1]
|
||||||
|
|
||||||
|
block:
|
||||||
|
iterator myIter(): auto {.inline.} =
|
||||||
|
yield 1
|
||||||
|
yield 2
|
||||||
|
|
||||||
|
doAssert myIter.toSeq == @[1, 2]
|
||||||
|
doAssert toSeq(myIter) == @[1, 2]
|
||||||
|
|
||||||
|
block:
|
||||||
|
iterator myIter(): int {.closure.} =
|
||||||
|
yield 1
|
||||||
|
yield 2
|
||||||
|
|
||||||
|
doAssert myIter.toSeq == @[1, 2]
|
||||||
|
doAssert toSeq(myIter) == @[1, 2]
|
||||||
|
|
||||||
|
block:
|
||||||
|
proc myIter(): auto =
|
||||||
|
iterator ret(): int {.closure.} =
|
||||||
|
yield 1
|
||||||
|
yield 2
|
||||||
|
result = ret
|
||||||
|
|
||||||
|
doAssert myIter().toSeq == @[1, 2]
|
||||||
|
doAssert toSeq(myIter()) == @[1, 2]
|
||||||
|
|
||||||
|
block:
|
||||||
|
proc myIter(n: int): auto =
|
||||||
|
var counter = 0
|
||||||
|
iterator ret(): int {.closure.} =
|
||||||
|
while counter < n:
|
||||||
|
yield counter
|
||||||
|
counter.inc
|
||||||
|
result = ret
|
||||||
|
|
||||||
|
block:
|
||||||
|
let myIter3 = myIter(3)
|
||||||
|
doAssert myIter3.toSeq == @[0, 1, 2]
|
||||||
|
block:
|
||||||
|
let myIter3 = myIter(3)
|
||||||
|
doAssert toSeq(myIter3) == @[0, 1, 2]
|
||||||
|
block:
|
||||||
|
# makes sure this does not hang forever
|
||||||
|
doAssert myIter(3).toSeq == @[0, 1, 2]
|
||||||
|
doAssert toSeq(myIter(3)) == @[0, 1, 2]
|
||||||
|
|
||||||
|
block:
|
||||||
|
# tests https://github.com/nim-lang/Nim/issues/7187
|
||||||
|
counter = 0
|
||||||
|
let ret = toSeq(@[1, 2, 3].identity().filter(proc (x: int): bool = x < 3))
|
||||||
|
doAssert ret == @[1, 2]
|
||||||
|
doAssert counter == 1
|
||||||
|
block: # foldl tests
|
||||||
|
let
|
||||||
|
numbers = @[5, 9, 11]
|
||||||
|
addition = foldl(numbers, a + b)
|
||||||
|
subtraction = foldl(numbers, a - b)
|
||||||
|
multiplication = foldl(numbers, a * b)
|
||||||
|
words = @["nim", "is", "cool"]
|
||||||
|
concatenation = foldl(words, a & b)
|
||||||
|
assert addition == 25, "Addition is (((5)+9)+11)"
|
||||||
|
assert subtraction == -15, "Subtraction is (((5)-9)-11)"
|
||||||
|
assert multiplication == 495, "Multiplication is (((5)*9)*11)"
|
||||||
|
assert concatenation == "nimiscool"
|
||||||
|
|
||||||
|
block: # foldr tests
|
||||||
|
let
|
||||||
|
numbers = @[5, 9, 11]
|
||||||
|
addition = foldr(numbers, a + b)
|
||||||
|
subtraction = foldr(numbers, a - b)
|
||||||
|
multiplication = foldr(numbers, a * b)
|
||||||
|
words = @["nim", "is", "cool"]
|
||||||
|
concatenation = foldr(words, a & b)
|
||||||
|
assert addition == 25, "Addition is (5+(9+(11)))"
|
||||||
|
assert subtraction == 7, "Subtraction is (5-(9-(11)))"
|
||||||
|
assert multiplication == 495, "Multiplication is (5*(9*(11)))"
|
||||||
|
assert concatenation == "nimiscool"
|
||||||
|
doAssert toSeq(1..3).foldr(a + b) == 6 # issue #14404
|
||||||
|
|
||||||
|
block: # mapIt + applyIt test
|
||||||
|
counter = 0
|
||||||
|
var
|
||||||
|
nums = @[1, 2, 3, 4]
|
||||||
|
strings = nums.identity.mapIt($(4 * it))
|
||||||
|
doAssert counter == 1
|
||||||
|
nums.applyIt(it * 3)
|
||||||
|
assert nums[0] + nums[3] == 15
|
||||||
|
assert strings[2] == "12"
|
||||||
|
|
||||||
|
block: # newSeqWith tests
|
||||||
|
var seq2D = newSeqWith(4, newSeq[bool](2))
|
||||||
|
seq2D[0][0] = true
|
||||||
|
seq2D[1][0] = true
|
||||||
|
seq2D[0][1] = true
|
||||||
|
doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]]
|
||||||
|
|
||||||
|
block: # mapLiterals tests
|
||||||
|
let x = mapLiterals([0.1, 1.2, 2.3, 3.4], int)
|
||||||
|
doAssert x is array[4, int]
|
||||||
|
doAssert mapLiterals((1, ("abc"), 2), float, nested = false) ==
|
||||||
|
(float(1), "abc", float(2))
|
||||||
|
doAssert mapLiterals(([1], ("abc"), 2), `$`, nested = true) ==
|
||||||
|
(["1"], "abc", "2")
|
||||||
|
|
||||||
|
block: # mapIt with openArray
|
||||||
|
counter = 0
|
||||||
|
proc foo(x: openArray[int]): seq[int] = x.mapIt(it * 10)
|
||||||
|
doAssert foo([identity(1), identity(2)]) == @[10, 20]
|
||||||
|
doAssert counter == 2
|
||||||
|
|
||||||
|
block: # mapIt with direct openArray
|
||||||
|
proc foo1(x: openArray[int]): seq[int] = x.mapIt(it * 10)
|
||||||
|
counter = 0
|
||||||
|
doAssert foo1(openArray[int]([identity(1), identity(2)])) == @[10, 20]
|
||||||
|
doAssert counter == 2
|
||||||
|
|
||||||
|
# Corner cases (openArray literals should not be common)
|
||||||
|
template foo2(x: openArray[int]): seq[int] = x.mapIt(it * 10)
|
||||||
|
counter = 0
|
||||||
|
doAssert foo2(openArray[int]([identity(1), identity(2)])) == @[10, 20]
|
||||||
|
# TODO: this fails; not sure how to fix this case
|
||||||
|
# doAssert counter == 2
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
doAssert openArray[int]([identity(1), identity(2)]).mapIt(it) == @[1, 2]
|
||||||
|
# ditto
|
||||||
|
# doAssert counter == 2
|
||||||
|
|
||||||
|
block: # mapIt empty test, see https://github.com/nim-lang/Nim/pull/8584#pullrequestreview-144723468
|
||||||
|
# NOTE: `[].mapIt(it)` is illegal, just as `let a = @[]` is (lacks type
|
||||||
|
# of elements)
|
||||||
|
doAssert: not compiles(mapIt(@[], it))
|
||||||
|
doAssert: not compiles(mapIt([], it))
|
||||||
|
doAssert newSeq[int](0).mapIt(it) == @[]
|
||||||
|
|
||||||
|
block: # mapIt redifinition check, see https://github.com/nim-lang/Nim/issues/8580
|
||||||
|
let s2 = [1, 2].mapIt(it)
|
||||||
|
doAssert s2 == @[1, 2]
|
||||||
|
|
||||||
|
block:
|
||||||
|
counter = 0
|
||||||
|
doAssert [1, 2].identity().mapIt(it*2).mapIt(it*10) == @[20, 40]
|
||||||
|
# https://github.com/nim-lang/Nim/issues/7187 test case
|
||||||
|
doAssert counter == 1
|
||||||
|
|
||||||
|
block: # mapIt with invalid RHS for `let` (#8566)
|
||||||
|
type X = enum
|
||||||
|
A, B
|
||||||
|
doAssert mapIt(X, $it) == @["A", "B"]
|
||||||
|
|
||||||
|
block:
|
||||||
|
# bug #9093
|
||||||
|
let inp = "a:b,c:d"
|
||||||
|
|
||||||
|
let outp = inp.split(",").mapIt(it.split(":"))
|
||||||
|
doAssert outp == @[@["a", "b"], @["c", "d"]]
|
||||||
|
|
||||||
|
|
||||||
|
block:
|
||||||
|
proc iter(len: int): auto =
|
||||||
|
result = iterator(): int =
|
||||||
|
for i in 0..<len:
|
||||||
|
yield i
|
||||||
|
|
||||||
|
doAssert: iter(3).mapIt(2*it).foldl(a + b) == 6
|
||||||
|
|
||||||
|
when not defined(testing):
|
||||||
|
echo "Finished doc tests"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue