diff options
author | Timothee Cour <timothee.cour2@gmail.com> | 2020-06-06 02:50:46 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-06 11:50:46 +0200 |
commit | d573581eb72997e27d91dac82b860964ed706590 (patch) | |
tree | b46e6f638f62fc5f51fa6c2223534bb5c7c8b02a /tests | |
parent | b19ad22b90b920036fcc7752eca624e55a929cf3 (diff) | |
download | Nim-d573581eb72997e27d91dac82b860964ed706590.tar.gz |
remove isMainModule from json,os,sequtils (#14572)
* move json.isMainModule => tjson * move isMainModule => tos,tsequtils
Diffstat (limited to 'tests')
-rw-r--r-- | tests/stdlib/tjson.nim | 234 | ||||
-rw-r--r-- | tests/stdlib/tos.nim | 63 | ||||
-rw-r--r-- | tests/stdlib/tsequtils.nim | 460 |
3 files changed, 757 insertions, 0 deletions
diff --git a/tests/stdlib/tjson.nim b/tests/stdlib/tjson.nim new file mode 100644 index 000000000..bc7ff02b2 --- /dev/null +++ b/tests/stdlib/tjson.nim @@ -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) diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim index 20e82173d..a440d86d8 100644 --- a/tests/stdlib/tos.nim +++ b/tests/stdlib/tos.nim @@ -447,3 +447,66 @@ block isRelativeTo: doAssert isRelativeTo("foo/bar", ".") doAssert not isRelativeTo("foo/bar.nims", "foo/bar.nim") 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") diff --git a/tests/stdlib/tsequtils.nim b/tests/stdlib/tsequtils.nim new file mode 100644 index 000000000..ea3f06982 --- /dev/null +++ b/tests/stdlib/tsequtils.nim @@ -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" |