diff options
Diffstat (limited to 'tests/collections')
-rw-r--r-- | tests/collections/tactiontable.nim | 37 | ||||
-rw-r--r-- | tests/collections/tcollections.nim | 105 | ||||
-rw-r--r-- | tests/collections/tcollections_to_string.nim | 115 | ||||
-rw-r--r-- | tests/collections/thashsets.nim | 382 | ||||
-rw-r--r-- | tests/collections/tseq.nim | 242 | ||||
-rw-r--r-- | tests/collections/ttables.nim | 457 | ||||
-rw-r--r-- | tests/collections/ttablesthreads.nim | 276 |
7 files changed, 1614 insertions, 0 deletions
diff --git a/tests/collections/tactiontable.nim b/tests/collections/tactiontable.nim new file mode 100644 index 000000000..3f15a70bd --- /dev/null +++ b/tests/collections/tactiontable.nim @@ -0,0 +1,37 @@ +discard """ + output: ''' +action 3 arg +action 3 arg +''' +""" + +import tables + +proc action1(arg: string) = + echo "action 1 ", arg + +proc action2(arg: string) = + echo "action 2 ", arg + +proc action3(arg: string) = + echo "action 3 ", arg + +proc action4(arg: string) = + echo "action 4 ", arg + +var + actionTable1 = { + "A": action1, + "B": action2, + "C": action3, + "D": action4}.toTable + +const + actionTable2 = { + "A": action1, + "B": action2, + "C": action3, + "D": action4}.toTable + +actionTable1["C"]("arg") +actionTable2["C"]("arg") diff --git a/tests/collections/tcollections.nim b/tests/collections/tcollections.nim new file mode 100644 index 000000000..7677f7c1a --- /dev/null +++ b/tests/collections/tcollections.nim @@ -0,0 +1,105 @@ +discard """ + targets: "c js" +""" + +# see also: tdeques, tlists, tcritbits + +import sets, tables, sequtils + +block tapply: + var x = @[1, 2, 3] + x.apply(proc(x: var int) = x = x+10) + x.apply(proc(x: int): int = x+100) + x.applyIt(it+5000) + doAssert x == @[5111, 5112, 5113] + +block tmapit: + var x = @[1, 2, 3] + # This mapIt call will run with preallocation because ``len`` is available. + var y = x.mapIt($(it+10)) + doAssert y == @["11", "12", "13"] + + type structureWithoutLen = object + a: array[5, int] + + iterator items(s: structureWithoutLen): int {.inline.} = + yield s.a[0] + yield s.a[1] + yield s.a[2] + yield s.a[3] + yield s.a[4] + + var st: structureWithoutLen + st.a[0] = 0 + st.a[1] = 1 + st.a[2] = 2 + st.a[3] = 3 + st.a[4] = 4 + + # this will run without preallocating the result + # since ``len`` is not available + var r = st.mapIt($(it+10)) + doAssert r == @["10", "11", "12", "13", "14"] + + + +# Collections to string: + +# Tests for tuples +doAssert $(1, 2, 3) == "(1, 2, 3)" +doAssert $("1", "2", "3") == """("1", "2", "3")""" +doAssert $('1', '2', '3') == """('1', '2', '3')""" + +# Tests for seqs +doAssert $(@[1, 2, 3]) == "@[1, 2, 3]" +doAssert $(@["1", "2", "3"]) == """@["1", "2", "3"]""" +doAssert $(@['1', '2', '3']) == """@['1', '2', '3']""" + +# Tests for sets +doAssert $(toHashSet([1])) == "{1}" +doAssert $(toHashSet(["1"])) == """{"1"}""" +doAssert $(toHashSet(['1'])) == """{'1'}""" +doAssert $(toOrderedSet([1, 2, 3])) == "{1, 2, 3}" +doAssert $(toOrderedSet(["1", "2", "3"])) == """{"1", "2", "3"}""" +doAssert $(toOrderedSet(['1', '2', '3'])) == """{'1', '2', '3'}""" + +# see also: tcritbitsToString, tlistsToString + +# Tests for tables +when defined(nimIntHash1): + doAssert $({1: "1", 2: "2"}.toTable) == """{1: "1", 2: "2"}""" +else: + doAssert $({1: "1", 2: "2"}.toTable) == """{2: "2", 1: "1"}""" +let tabStr = $({"1": 1, "2": 2}.toTable) +doAssert (tabStr == """{"2": 2, "1": 1}""" or tabStr == """{"1": 1, "2": 2}""") + +# Test escaping behavior +block: + var s = "" + s.addQuoted('\0') + s.addQuoted('\31') + s.addQuoted('\127') + doAssert s == "'\\x00''\\x1F''\\x7F'" +block: + var s = "" + s.addQuoted('\\') + s.addQuoted('\'') + s.addQuoted('\"') + doAssert s == """'\\''\'''\"'""" +block: + var s = "" + s.addQuoted("å") + s.addQuoted("ä") + s.addQuoted("ö") + s.addEscapedChar('\xFF') + doAssert s == """"å""ä""ö"\xFF""" + +# Test customized element representation +type CustomString = object + +proc addQuoted(s: var string, x: CustomString) = + s.add("<CustomString>") + +block: + let s = @[CustomString()] + doAssert $s == "@[<CustomString>]" diff --git a/tests/collections/tcollections_to_string.nim b/tests/collections/tcollections_to_string.nim new file mode 100644 index 000000000..62ba87334 --- /dev/null +++ b/tests/collections/tcollections_to_string.nim @@ -0,0 +1,115 @@ +discard """ + exitcode: 0 + output: "" +""" +import sets +import tables +import deques +import lists +import critbits + +# Tests for tuples +doAssert $(1, 2, 3) == "(1, 2, 3)" +doAssert $("1", "2", "3") == """("1", "2", "3")""" +doAssert $('1', '2', '3') == """('1', '2', '3')""" + +# Tests for seqs +doAssert $(@[1, 2, 3]) == "@[1, 2, 3]" +doAssert $(@["1", "2", "3"]) == """@["1", "2", "3"]""" +doAssert $(@['1', '2', '3']) == """@['1', '2', '3']""" + +# Tests for sets +doAssert $(toHashSet([1])) == "{1}" +doAssert $(toHashSet(["1"])) == """{"1"}""" +doAssert $(toHashSet(['1'])) == """{'1'}""" +doAssert $(toOrderedSet([1, 2, 3])) == "{1, 2, 3}" +doAssert $(toOrderedSet(["1", "2", "3"])) == """{"1", "2", "3"}""" +doAssert $(toOrderedSet(['1', '2', '3'])) == """{'1', '2', '3'}""" + +# Tests for tables +when defined(nimIntHash1): + doAssert $({1: "1", 2: "2"}.toTable) == """{1: "1", 2: "2"}""" +else: + doAssert $({1: "1", 2: "2"}.toTable) == """{2: "2", 1: "1"}""" +doAssert $({"1": 1, "2": 2}.toTable) == """{"1": 1, "2": 2}""" + +# Tests for deques +block: + var d = initDeque[int]() + d.addLast(1) + doAssert $d == "[1]" +block: + var d = initDeque[string]() + d.addLast("1") + doAssert $d == """["1"]""" +block: + var d = initDeque[char]() + d.addLast('1') + doAssert $d == "['1']" + +# Tests for lists +block: + var l = initDoublyLinkedList[int]() + l.append(1) + l.append(2) + l.append(3) + doAssert $l == "[1, 2, 3]" +block: + var l = initDoublyLinkedList[string]() + l.append("1") + l.append("2") + l.append("3") + doAssert $l == """["1", "2", "3"]""" +block: + var l = initDoublyLinkedList[char]() + l.append('1') + l.append('2') + l.append('3') + doAssert $l == """['1', '2', '3']""" + +# Tests for critbits +block: + var t: CritBitTree[int] + t["a"] = 1 + doAssert $t == """{"a": 1}""" +block: + var t: CritBitTree[string] + t["a"] = "1" + doAssert $t == """{"a": "1"}""" +block: + var t: CritBitTree[char] + t["a"] = '1' + doAssert $t == """{"a": '1'}""" + + +# Test escaping behavior +block: + var s = "" + s.addQuoted('\0') + s.addQuoted('\31') + s.addQuoted('\127') + doAssert s == "'\\x00''\\x1F''\\x7F'" +block: + var s = "" + s.addQuoted('\\') + s.addQuoted('\'') + s.addQuoted('\"') + doAssert s == """'\\''\'''\"'""" +block: + var s = "" + s.addQuoted("å") + s.addQuoted("ä") + s.addQuoted("ö") + s.addEscapedChar('\xFF') + doAssert s == """"å""ä""ö"\xFF""" + +# Test customized element representation +type CustomString = object + +proc addQuoted(s: var string, x: CustomString) = + s.add("<CustomString>") + +block: + let s = @[CustomString()] + doAssert $s == "@[<CustomString>]" + diff --git a/tests/collections/thashsets.nim b/tests/collections/thashsets.nim new file mode 100644 index 000000000..359eaa51e --- /dev/null +++ b/tests/collections/thashsets.nim @@ -0,0 +1,382 @@ +import sets, hashes, algorithm + + +block setEquality: + var + a = initHashSet[int]() + b = initHashSet[int]() + c = initHashSet[string]() + + for i in 0..5: a.incl(i) + for i in 1..6: b.incl(i) + for i in 0..5: c.incl($i) + + doAssert map(a, proc(x: int): int = x + 1) == b + doAssert map(a, proc(x: int): string = $x) == c + + +block setsContainingTuples: + var set = initHashSet[tuple[i: int, i64: int64, f: float]]() + set.incl( (i: 123, i64: 123'i64, f: 3.14) ) + doAssert set.contains( (i: 123, i64: 123'i64, f: 3.14) ) + doAssert( not set.contains( (i: 456, i64: 789'i64, f: 2.78) ) ) + + +block setWithTuplesWithSeqs: + var s = initHashSet[tuple[s: seq[int]]]() + s.incl( (s: @[1, 2, 3]) ) + doAssert s.contains( (s: @[1, 2, 3]) ) + doAssert( not s.contains((s: @[4, 5, 6])) ) + + +block setWithSequences: + var s = initHashSet[seq[int]]() + s.incl( @[1, 2, 3] ) + doAssert s.contains(@[1, 2, 3]) + doAssert( not s.contains(@[4, 5, 6]) ) + +block setClearWorked: + var s = initHashSet[char]() + + for c in "this is a test": + s.incl(c) + + doAssert len(s) == 7 + clear(s) + doAssert len(s) == 0 + + s.incl('z') + for c in "this is a test": + s.incl(c) + + doAssert len(s) == 8 + +block orderedSetClearWorked: + var s = initOrderedSet[char]() + + for c in "eat at joes": + s.incl(c) + + var r = "" + + for c in items(s): + add(r, c) + + doAssert r == "eat jos" + clear(s) + + s.incl('z') + for c in "eat at joes": + s.incl(c) + + r = "" + for c in items(s): + add(r, c) + + doAssert r == "zeat jos" + +block hashForHashedSet: + let + seq1 = "This is the test." + seq2 = "the test is This." + s1 = seq1.toHashSet() + s2 = seq2.toHashSet() + doAssert s1 == s2 + doAssert hash(s1) == hash(s2) + +block hashForOrderdSet: + let + str = "This is the test." + rstr = str.reversed + + var + s1 = initOrderedSet[char]() + s2 = initOrderedSet[char]() + r = initOrderedSet[char]() + expected: Hash + added: seq[char] = @[] + reversed: Hash + radded: seq[char] = @[] + + expected = 0 + for c in str: + if (not (c in added)): + expected = expected !& hash(c) + added.add(c) + s1.incl(c) + s2.incl(c) + expected = !$expected + doAssert hash(s1) == expected + doAssert hash(s1) == hash(s2) + doAssert hash(s1) != hash(r) + + reversed = 0 + for c in rstr: + if (not (c in radded)): + reversed = reversed !& hash(c) + radded.add(c) + r.incl(c) + reversed = !$reversed + doAssert hash(r) == reversed + doAssert hash(s1) != reversed + + +proc testModule() = + ## Internal micro test to validate docstrings and such. + block lenTest: + var values: HashSet[int] + doAssert values.len == 0 + doAssert values.card == 0 + + block setIterator: + type pair = tuple[a, b: int] + var a, b = initHashSet[pair]() + a.incl((2, 3)) + a.incl((3, 2)) + a.incl((2, 3)) + for x, y in a.items: + b.incl((x - 2, y + 1)) + doAssert a.len == b.card + doAssert a.len == 2 + #echo b + + block setContains: + var values = initHashSet[int]() + doAssert(not values.contains(2)) + values.incl(2) + doAssert values.contains(2) + values.excl(2) + doAssert(not values.contains(2)) + + values.incl(4) + var others = toHashSet([6, 7]) + values.incl(others) + doAssert values.len == 3 + + values.init + doAssert values.containsOrIncl(2) == false + doAssert values.containsOrIncl(2) == true + var + a = toHashSet([1, 2]) + b = toHashSet([1]) + b.incl(2) + doAssert a == b + + block exclusions: + var s = toHashSet([2, 3, 6, 7]) + s.excl(2) + s.excl(2) + doAssert s.len == 3 + + var + numbers = toHashSet([1, 2, 3, 4, 5]) + even = toHashSet([2, 4, 6, 8]) + numbers.excl(even) + #echo numbers + # --> {1, 3, 5} + + block toSeqAndString: + var a = toHashSet([2, 7, 5]) + var b = initHashSet[int](a.len) + for x in [2, 7, 5]: b.incl(x) + doAssert($a == $b) + #echo a + #echo toHashSet(["no", "esc'aping", "is \" provided"]) + + #block orderedToSeqAndString: + # echo toOrderedSet([2, 4, 5]) + # echo toOrderedSet(["no", "esc'aping", "is \" provided"]) + + block setOperations: + var + a = toHashSet(["a", "b"]) + b = toHashSet(["b", "c"]) + c = union(a, b) + doAssert c == toHashSet(["a", "b", "c"]) + var d = intersection(a, b) + doAssert d == toHashSet(["b"]) + var e = difference(a, b) + doAssert e == toHashSet(["a"]) + var f = symmetricDifference(a, b) + doAssert f == toHashSet(["a", "c"]) + doAssert d < a and d < b + doAssert((a < a) == false) + doAssert d <= a and d <= b + doAssert((a <= a)) + # Alias test. + doAssert a + b == toHashSet(["a", "b", "c"]) + doAssert a * b == toHashSet(["b"]) + doAssert a - b == toHashSet(["a"]) + doAssert a -+- b == toHashSet(["a", "c"]) + doAssert disjoint(a, b) == false + doAssert disjoint(a, b - a) == true + + block mapSet: + var a = toHashSet([1, 2, 3]) + var b = a.map(proc (x: int): string = $x) + doAssert b == toHashSet(["1", "2", "3"]) + + block lenTest: + var values: OrderedSet[int] + doAssert values.len == 0 + doAssert values.card == 0 + + block setIterator: + type pair = tuple[a, b: int] + var a, b = initOrderedSet[pair]() + a.incl((2, 3)) + a.incl((3, 2)) + a.incl((2, 3)) + for x, y in a.items: + b.incl((x - 2, y + 1)) + doAssert a.len == b.card + doAssert a.len == 2 + + block setPairsIterator: + var s = toOrderedSet([1, 3, 5, 7]) + var items = newSeq[tuple[a: int, b: int]]() + for idx, item in s: items.add((idx, item)) + doAssert items == @[(0, 1), (1, 3), (2, 5), (3, 7)] + + block exclusions: + var s = toOrderedSet([1, 2, 3, 6, 7, 4]) + + s.excl(3) + s.excl(3) + s.excl(1) + s.excl(4) + + var items = newSeq[int]() + for item in s: items.add item + doAssert items == @[2, 6, 7] + + block: #9005 + var s = initOrderedSet[(int, int)]() + for i in 0 .. 30: incl(s, (i, 0)) + for i in 0 .. 30: excl(s, (i, 0)) + doAssert s.len == 0 + + #block orderedSetIterator: + # var a = initOrderedSet[int]() + # for value in [9, 2, 1, 5, 1, 8, 4, 2]: + # a.incl(value) + # for value in a.items: + # echo "Got ", value + + block setContains: + var values = initOrderedSet[int]() + doAssert(not values.contains(2)) + values.incl(2) + doAssert values.contains(2) + + block toSeqAndString: + var a = toOrderedSet([2, 4, 5]) + var b = initOrderedSet[int]() + for x in [2, 4, 5]: b.incl(x) + doAssert($a == $b) + doAssert(a == b) # https://github.com/Araq/Nim/issues/1413 + + block initBlocks: + var a: OrderedSet[int] + a.init(4) + a.incl(2) + a.init + doAssert a.len == 0 + a = initOrderedSet[int](4) + a.incl(2) + doAssert a.len == 1 + + var b: HashSet[int] + b.init(4) + b.incl(2) + b.init + doAssert b.len == 0 + b = initHashSet[int](4) + b.incl(2) + doAssert b.len == 1 + + block missingOrExcl: + var s = toOrderedSet([2, 3, 6, 7]) + doAssert s.missingOrExcl(4) == true + doAssert s.missingOrExcl(6) == false + + block orderedSetEquality: + type pair = tuple[a, b: int] + + var aa = initOrderedSet[pair]() + var bb = initOrderedSet[pair]() + + var x = (a: 1, b: 2) + var y = (a: 3, b: 4) + + aa.incl(x) + aa.incl(y) + + bb.incl(x) + bb.incl(y) + doAssert aa == bb + + block setsWithoutInit: + var + a: HashSet[int] + b: HashSet[int] + c: HashSet[int] + d: HashSet[int] + e: HashSet[int] + + doAssert a.containsOrIncl(3) == false + doAssert a.contains(3) + doAssert a.len == 1 + doAssert a.containsOrIncl(3) + a.incl(3) + doAssert a.len == 1 + a.incl(6) + doAssert a.len == 2 + + b.incl(5) + doAssert b.len == 1 + b.excl(5) + b.excl(c) + doAssert b.missingOrExcl(5) + doAssert b.disjoint(c) + + d = b + c + doAssert d.len == 0 + d = b * c + doAssert d.len == 0 + d = b - c + doAssert d.len == 0 + d = b -+- c + doAssert d.len == 0 + + doAssert (d < e) == false + doAssert d <= e + doAssert d == e + + block setsWithoutInit: + var + a: OrderedSet[int] + b: OrderedSet[int] + c: OrderedSet[int] + d: HashSet[int] + + + doAssert a.containsOrIncl(3) == false + doAssert a.contains(3) + doAssert a.len == 1 + doAssert a.containsOrIncl(3) + a.incl(3) + doAssert a.len == 1 + a.incl(6) + doAssert a.len == 2 + + b.incl(5) + doAssert b.len == 1 + doAssert b.missingOrExcl(5) == false + doAssert b.missingOrExcl(5) + + doAssert c.missingOrExcl(9) + d.incl(c) + doAssert d.len == 0 + +testModule() diff --git a/tests/collections/tseq.nim b/tests/collections/tseq.nim new file mode 100644 index 000000000..0f8084c78 --- /dev/null +++ b/tests/collections/tseq.nim @@ -0,0 +1,242 @@ +discard """ + matrix: "--mm:refc; --mm:orc" + output: ''' +Hithere, what's your name?Hathere, what's your name? +fA13msg1falsefB14msg2truefC15msg3false +Zip: [{"Field0": 1, "Field1": 2}, {"Field0": 3, "Field1": 4}, {"Field0": 5, "Field1": 6}] +Filter Iterator: 3 +Filter Iterator: 5 +Filter Iterator: 7 +Filter: [3, 5, 7] +FilterIt: [1, 3, 7] +Concat: [1, 3, 5, 7, 2, 4, 6] +Deduplicate: [1, 2, 3, 4, 5, 7] +@[()] +Minmax: (1, 7) +2345623456 +''' +""" + +block tseq2: + proc `*`(a, b: seq[int]): seq[int] = + # allocate a new sequence: + newSeq(result, len(a)) + # multiply two int sequences: + for i in 0..len(a)-1: result[i] = a[i] * b[i] + + doAssert(@[1, 2, 3] * @[1, 2, 3] == @[1, 4, 9]) + + + +block tseqcon: + const nestedFixed = true + + type + TRec {.final.} = object + x, y: int + s: string + seq: seq[string] + TRecSeq = seq[TRec] + + proc test() = + var s, b: seq[string] + s = @[] + add(s, "Hi") + add(s, "there, ") + add(s, "what's your name?") + + b = s # deep copying here! + b[0][1] = 'a' + + for i in 0 .. len(s)-1: + write(stdout, s[i]) + for i in 0 .. len(b)-1: + write(stdout, b[i]) + + when nestedFixed: + proc nested() = + var + s: seq[seq[string]] + for i in 0..10_000: # test if the garbage collector + # now works with sequences + s = @[ + @["A", "B", "C", "D"], + @["E", "F", "G", "H"], + @["I", "J", "K", "L"], + @["M", "N", "O", "P"]] + + test() + when nestedFixed: + nested() + echo "" + + + +import os +block tseqcon2: + proc rec_dir(dir: string): seq[string] = + result = @[] + for kind, path in walk_dir(dir): + if kind == pcDir: + add(result, rec_dir(path)) + else: + add(result, path) + + + +block tseqtuple: + type + TMsg = tuple[ + file: string, + line: int, + msg: string, + err: bool] + + var s: seq[TMsg] = @[] + + s.add(("fA", 13, "msg1", false)) + s.add(("fB", 14, "msg2", true)) + s.add(("fC", 15, "msg3", false)) + + for file, line, msg, err in items(s): + stdout.write(file) + stdout.write($line) + stdout.write(msg) + stdout.write($err) + echo "" + + +import sequtils, marshal +block tsequtils: + proc testFindWhere(item : int) : bool = + if item != 1: return true + + var seq1: seq[int] = @[] + + seq1.add(1) + seq1.add(3) + seq1.add(5) + seq1.add(7) + + var seq2: seq[int] = @[2, 4, 6] + var final = zip(seq1, seq2) + + echo "Zip: ", $$(final) + + #Test findWhere as a iterator + + for itms in filter(seq1, testFindWhere): + echo "Filter Iterator: ", $$(itms) + + + #Test findWhere as a proc + + var fullseq: seq[int] = filter(seq1, testFindWhere) + + echo "Filter: ", $$(fullseq) + + #Test findIt as a template + + var finditval: seq[int] = filterIt(seq1, it!=5) + + echo "FilterIt: ", $$(finditval) + + var concatseq = concat(seq1,seq2) + echo "Concat: ", $$(concatseq) + + var seq3 = @[1,2,3,4,5,5,5,7] + var dedupseq = deduplicate(seq3) + echo "Deduplicate: ", $$(dedupseq) + # bug #4973 + type + SomeObj = object + OtherObj = object + field: SomeObj + + let aSeq = @[OtherObj(field: SomeObj())] + let someObjSeq = aSeq.mapIt(it.field) + echo someObjSeq + + block minmax: + doAssert minmax(@[0]) == (0, 0) + doAssert minmax(@[0, 1]) == (0, 1) + doAssert minmax(@[1, 0]) == (0, 1) + doAssert minmax(@[8,2,1,7,3,9,4,0,5]) == (0, 9) + echo "Minmax: ", $(minmax(concat(seq1, seq2))) + + +when not defined(nimseqsv2): + block tshallowseq: + proc xxx() = + var x: seq[int] = @[1, 2, 3] + var y: seq[int] + system.shallowCopy(y, x) + y[1] = 42 + doAssert y == @[1, 42, 3] + doAssert x == @[1, 42, 3] + xxx() + + + block tshallowemptyseq: + proc test() = + var nilSeq: seq[int] = @[] + var emptySeq: seq[int] = newSeq[int]() + block: + var t = @[1,2,3] + when defined(gcRefc): + shallow(nilSeq) + t = nilSeq + doAssert t == @[] + block: + var t = @[1,2,3] + when defined(gcRefc): + shallow(emptySeq) + t = emptySeq + doAssert t == @[] + block: + var t = @[1,2,3] + shallowCopy(t, nilSeq) + doAssert t == @[] + block: + var t = @[1,2,3] + shallowCopy(t, emptySeq) + doAssert t == @[] + test() + + +import strutils +block ttoseq: + for x in toSeq(countup(2, 6)): + stdout.write(x) + for x in items(toSeq(countup(2, 6))): + stdout.write(x) + var y: typeof("a b c".split) + y = "xzy" + stdout.write("\n") + +block tseqmapitchain: + doAssert @[101, 102] == [1, 2].mapIt(func (x: int): int = it + x).mapIt(it(100)) + + +for i in 0..100: + # fix #14655 + var test = newSeqOfCap[uint32](1) + test.setLen(1) + doAssert test[0] == 0, $(test[0], i) + + +# bug #22560 +doAssert len(newSeqOfCap[int](42)) == 0 + +block: # bug #17197 + type Matrix = seq[seq[int]] + + proc needlemanWunsch(sequence1: string, sequence2: string, gap_penal: int8, match: int8, indel_penal: int8): bool = + let seq2_len = sequence2.len + + var grid: Matrix + for i in sequence1: + grid.add(newSeqOfCap[seq[int]](seq2_len)) + result = true + + doAssert needlemanWunsch("ABC", "DEFG", 1, 2, 3) diff --git a/tests/collections/ttables.nim b/tests/collections/ttables.nim new file mode 100644 index 000000000..95f9418a0 --- /dev/null +++ b/tests/collections/ttables.nim @@ -0,0 +1,457 @@ +discard """ +output: ''' +done tableadds +And we get here +1 +2 +3 +''' +joinable: false +targets: "c cpp js" +""" + +# xxx wrap in a template to test in VM, see https://github.com/timotheecour/Nim/issues/534#issuecomment-769565033 + +import hashes, sequtils, tables, algorithm + +proc sortedPairs[T](t: T): auto = toSeq(t.pairs).sorted +template sortedItems(t: untyped): untyped = sorted(toSeq(t)) + +block tableDollar: + # other tests should use `sortedPairs` to be robust to future table/hash + # implementation changes + doAssert ${1: 'a', 2: 'b'}.toTable in ["{1: 'a', 2: 'b'}", "{2: 'b', 1: 'a'}"] + +# test should not be joined because it takes too long. +block tableadds: + proc main = + var tab = newTable[string, string]() + for i in 0..1000: + tab["key"] = "value " & $i + + main() + echo "done tableadds" + + +block tcounttable: + # bug #2625 + const s_len = 32 + var substr_counts: CountTable[string] = initCountTable[string]() + var my_string = "Hello, this is sadly broken for strings over 64 characters. Note that it *does* appear to work for short strings." + for i in 0..(my_string.len - s_len): + let s = my_string[i..i+s_len-1] + substr_counts[s] = 1 + # substr_counts[s] = substr_counts[s] + 1 # Also breaks, + 2 as well, etc. + # substr_counts.inc(s) # This works + #echo "Iteration ", i + + echo "And we get here" + + +block thashes: + # Test with int + block: + var t = initTable[int,int]() + t[0] = 42 + t[1] = t[0] + 1 + doAssert(t[0] == 42) + doAssert(t[1] == 43) + let t2 = {1: 1, 2: 2}.toTable + doAssert(t2[2] == 2) + + # Test with char + block: + var t = initTable[char,int]() + t['0'] = 42 + t['1'] = t['0'] + 1 + doAssert(t['0'] == 42) + doAssert(t['1'] == 43) + let t2 = {'1': 1, '2': 2}.toTable + doAssert(t2['2'] == 2) + + # Test with enum + block: + type + E = enum eA, eB, eC + var t = initTable[E,int]() + t[eA] = 42 + t[eB] = t[eA] + 1 + doAssert(t[eA] == 42) + doAssert(t[eB] == 43) + let t2 = {eA: 1, eB: 2}.toTable + doAssert(t2[eB] == 2) + + # Test with range + block: + type + R = range[0..9] + var t = initTable[R,int]() # causes warning, why? + t[1] = 42 # causes warning, why? + t[2] = t[1] + 1 + doAssert(t[1] == 42) + doAssert(t[2] == 43) + let t2 = {1.R: 1, 2.R: 2}.toTable + doAssert(t2[2.R] == 2) + + # Test which combines the generics for tuples + ordinals + block: + type + E = enum eA, eB, eC + var t = initTable[(string, E, int, char), int]() + t[("a", eA, 0, '0')] = 42 + t[("b", eB, 1, '1')] = t[("a", eA, 0, '0')] + 1 + doAssert(t[("a", eA, 0, '0')] == 42) + doAssert(t[("b", eB, 1, '1')] == 43) + let t2 = {("a", eA, 0, '0'): 1, ("b", eB, 1, '1'): 2}.toTable + doAssert(t2[("b", eB, 1, '1')] == 2) + + # Test to check if overloading is possible + # Unfortunately, this does not seem to work for int + # The same test with a custom hash(s: string) does + # work though. + block: + proc hash(x: int): Hash {.inline.} = + echo "overloaded hash" + result = x + var t = initTable[int, int]() + t[0] = 0 + + # Check hashability of all integer types (issue #5429) + block: + let intTables = ( + newTable[int, string](), + newTable[int8, string](), + newTable[int16, string](), + newTable[int32, string](), + newTable[int64, string](), + newTable[uint, string](), + newTable[uint8, string](), + newTable[uint16, string](), + newTable[uint32, string](), + newTable[uint64, string](), + ) + echo "1" + + +block tindexby: + doAssert indexBy(newSeq[int](), proc(x: int):int = x) == initTable[int, int](), "empty int table" + + var tbl1 = initTable[int, int]() + tbl1[1] = 1 + tbl1[2] = 2 + doAssert indexBy(@[1,2], proc(x: int):int = x) == tbl1, "int table" + + type + TElem = object + foo: int + bar: string + + let + elem1 = TElem(foo: 1, bar: "bar") + elem2 = TElem(foo: 2, bar: "baz") + + var tbl2 = initTable[string, TElem]() + tbl2["bar"] = elem1 + tbl2["baz"] = elem2 + doAssert indexBy(@[elem1,elem2], proc(x: TElem): string = x.bar) == tbl2, "element table" + + +block tableconstr: + # Test if the new table constructor syntax works: + + template ignoreExpr(e) = + discard + + # test first class '..' syntactical citizen: + ignoreExpr x <> 2..4 + # test table constructor: + ignoreExpr({:}) + ignoreExpr({2: 3, "key": "value"}) + + # NEW: + doAssert 56 in 50..100 + + doAssert 56 in 0..60 + + +block ttables2: + proc TestHashIntInt() = + var tab = initTable[int,int]() + let n = 10 + for i in 1..n: + tab[i] = i + for i in 1..n: + var x = tab[i] + if x != i : echo "not found ", i + + TestHashIntInt() + + # bug #2107 + + var delTab = initTable[int,int](4) + + for i in 1..4: + delTab[i] = i + delTab.del(i) + delTab[5] = 5 + + + echo "2" + +block tablesref: + const + data = { + "34": 123456, "12": 789, + "90": 343, "0": 34404, + "1": 344004, "2": 344774, + "3": 342244, "4": 3412344, + "5": 341232144, "6": 34214544, + "7": 3434544, "8": 344544, + "9": 34435644, "---00": 346677844, + "10": 34484, "11": 34474, "19": 34464, + "20": 34454, "30": 34141244, "40": 344114, + "50": 344490, "60": 344491, "70": 344492, + "80": 344497} + + sorteddata = { + "---00": 346677844, + "0": 34404, + "1": 344004, + "10": 34484, + "11": 34474, + "12": 789, + "19": 34464, + "2": 344774, "20": 34454, + "3": 342244, "30": 34141244, + "34": 123456, + "4": 3412344, "40": 344114, + "5": 341232144, "50": 344490, + "6": 34214544, "60": 344491, + "7": 3434544, "70": 344492, + "8": 344544, "80": 344497, + "9": 34435644, + "90": 343} + + block tableTest1: + var t = newTable[tuple[x, y: int], string]() + t[(0,0)] = "00" + t[(1,0)] = "10" + t[(0,1)] = "01" + t[(1,1)] = "11" + for x in 0..1: + for y in 0..1: + doAssert t[(x,y)] == $x & $y + doAssert t.sortedPairs == + @[((x: 0, y: 0), "00"), ((x: 0, y: 1), "01"), ((x: 1, y: 0), "10"), ((x: 1, y: 1), "11")] + + block tableTest2: + var t = newTable[string, float]() + t["test"] = 1.2345 + t["111"] = 1.000043 + t["123"] = 1.23 + t.del("111") + + t["012"] = 67.9 + t["123"] = 1.5 # test overwriting + + doAssert t["123"] == 1.5 + try: + echo t["111"] # deleted + except KeyError: + discard + doAssert(not hasKey(t, "111")) + doAssert "111" notin t + + for key, val in items(data): t[key] = val.toFloat + for key, val in items(data): doAssert t[key] == val.toFloat + + + block orderedTableTest1: + var t = newOrderedTable[string, int](2) + for key, val in items(data): t[key] = val + for key, val in items(data): doAssert t[key] == val + var i = 0 + # `pairs` needs to yield in insertion order: + for key, val in pairs(t): + doAssert key == data[i][0] + doAssert val == data[i][1] + inc(i) + + for key, val in mpairs(t): val = 99 + for val in mvalues(t): doAssert val == 99 + + block countTableTest1: + var s = data.toTable + var t = newCountTable[string]() + var r = newCountTable[string]() + for x in [t, r]: + for k in s.keys: + x.inc(k) + doAssert x[k] == 1 + x.inc("90", 3) + x.inc("12", 2) + x.inc("34", 1) + doAssert t.largest()[0] == "90" + + t.sort() + r.sort(SortOrder.Ascending) + var ps1 = toSeq t.pairs + var ps2 = toSeq r.pairs + ps2.reverse() + for ps in [ps1, ps2]: + var i = 0 + for (k, v) in ps: + case i + of 0: doAssert k == "90" and v == 4 + of 1: doAssert k == "12" and v == 3 + of 2: doAssert k == "34" and v == 2 + else: break + inc i + + block smallestLargestNamedFieldsTest: # bug #14918 + const a = [7, 8, 8] + + proc testNamedFields(t: CountTable | CountTableRef) = + doAssert t.smallest.key == 7 + doAssert t.smallest.val == 1 + doAssert t.largest.key == 8 + doAssert t.largest.val == 2 + + let t1 = toCountTable(a) + testNamedFields(t1) + let t2 = newCountTable(a) + testNamedFields(t2) + + block SyntaxTest: + var x = newTable[int, string]({:}) + discard x + + block nilTest: + var i, j: TableRef[int, int] = nil + doAssert i == j + j = newTable[int, int]() + doAssert i != j + doAssert j != i + i = newTable[int, int]() + doAssert i == j + + proc orderedTableSortTest() = + var t = newOrderedTable[string, int](2) + for key, val in items(data): t[key] = val + for key, val in items(data): doAssert t[key] == val + proc cmper(x, y: tuple[key: string, val: int]): int = cmp(x.key, y.key) + t.sort(cmper) + var i = 0 + # `pairs` needs to yield in sorted order: + for key, val in pairs(t): + doAssert key == sorteddata[i][0] + doAssert val == sorteddata[i][1] + inc(i) + t.sort(cmper, order=SortOrder.Descending) + i = 0 + for key, val in pairs(t): + doAssert key == sorteddata[high(data)-i][0] + doAssert val == sorteddata[high(data)-i][1] + inc(i) + + # check that lookup still works: + for key, val in pairs(t): + doAssert val == t[key] + # check that insert still works: + t["newKeyHere"] = 80 + + block anonZipTest: + let keys = @['a','b','c'] + let values = @[1, 2, 3] + doAssert zip(keys, values).toTable.sortedPairs == @[('a', 1), ('b', 2), ('c', 3)] + + block clearTableTest: + var t = newTable[string, float]() + t["test"] = 1.2345 + t["111"] = 1.000043 + t["123"] = 1.23 + doAssert t.len() != 0 + t.clear() + doAssert t.len() == 0 + + block clearOrderedTableTest: + var t = newOrderedTable[string, int](2) + for key, val in items(data): t[key] = val + doAssert t.len() != 0 + t.clear() + doAssert t.len() == 0 + + block clearCountTableTest: + var t = newCountTable[string]() + t.inc("90", 3) + t.inc("12", 2) + t.inc("34", 1) + doAssert t.len() != 0 + t.clear() + doAssert t.len() == 0 + + orderedTableSortTest() + echo "3" + + +block: # https://github.com/nim-lang/Nim/issues/13496 + template testDel(body) = + block: + body + when t is CountTable|CountTableRef: + t.inc(15, 1) + t.inc(19, 2) + t.inc(17, 3) + t.inc(150, 4) + t.del(150) + else: + t[15] = 1 + t[19] = 2 + t[17] = 3 + t[150] = 4 + t.del(150) + doAssert t.len == 3 + doAssert sortedItems(t.values) == @[1, 2, 3] + doAssert sortedItems(t.keys) == @[15, 17, 19] + doAssert sortedPairs(t) == @[(15, 1), (17, 3), (19, 2)] + var s = newSeq[int]() + for v in t.values: s.add(v) + doAssert s.len == 3 + doAssert sortedItems(s) == @[1, 2, 3] + when t is OrderedTable|OrderedTableRef: + doAssert toSeq(t.keys) == @[15, 19, 17] + doAssert toSeq(t.values) == @[1,2,3] + doAssert toSeq(t.pairs) == @[(15, 1), (19, 2), (17, 3)] + + testDel(): (var t: Table[int, int]) + testDel(): (let t = newTable[int, int]()) + testDel(): (var t: OrderedTable[int, int]) + testDel(): (let t = newOrderedTable[int, int]()) + testDel(): (var t: CountTable[int]) + testDel(): (let t = newCountTable[int]()) + + +block testNonPowerOf2: + var a = initTable[int, int](7) + a[1] = 10 + doAssert a[1] == 10 + + var b = initTable[int, int](9) + b[1] = 10 + doAssert b[1] == 10 + +block emptyOrdered: + var t1: OrderedTable[int, string] + var t2: OrderedTable[int, string] + doAssert t1 == t2 + +block: # Table[ref, int] + type A = ref object + x: int + var t: OrderedTable[A, int] + let a1 = A(x: 3) + let a2 = A(x: 3) + t[a1] = 10 + t[a2] = 11 + doAssert t[a1] == 10 + doAssert t[a2] == 11 diff --git a/tests/collections/ttablesthreads.nim b/tests/collections/ttablesthreads.nim new file mode 100644 index 000000000..2a4e1bf42 --- /dev/null +++ b/tests/collections/ttablesthreads.nim @@ -0,0 +1,276 @@ +discard """ + cmd: "nim c --threads:on $file" + output: '''true''' +""" + +import hashes, tables, sharedtables, algorithm, sequtils + +proc sortedPairs[T](t: T): auto = toSeq(t.pairs).sorted + +const + data = { + "34": 123456, "12": 789, + "90": 343, "0": 34404, + "1": 344004, "2": 344774, + "3": 342244, "4": 3412344, + "5": 341232144, "6": 34214544, + "7": 3434544, "8": 344544, + "9": 34435644, "---00": 346677844, + "10": 34484, "11": 34474, "19": 34464, + "20": 34454, "30": 34141244, "40": 344114, + "50": 344490, "60": 344491, "70": 344492, + "80": 344497} + + sorteddata = { + "---00": 346677844, + "0": 34404, + "1": 344004, + "10": 34484, + "11": 34474, + "12": 789, + "19": 34464, + "2": 344774, "20": 34454, + "3": 342244, "30": 34141244, + "34": 123456, + "4": 3412344, "40": 344114, + "5": 341232144, "50": 344490, + "6": 34214544, "60": 344491, + "7": 3434544, "70": 344492, + "8": 344544, "80": 344497, + "9": 34435644, + "90": 343} + +block tableTest1: + var t = initTable[tuple[x, y: int], string]() + t[(0,0)] = "00" + t[(1,0)] = "10" + t[(0,1)] = "01" + t[(1,1)] = "11" + for x in 0..1: + for y in 0..1: + doAssert t[(x,y)] == $x & $y + doAssert t.sortedPairs == @[((x: 0, y: 0), "00"), ((x: 0, y: 1), "01"), ((x: 1, y: 0), "10"), ((x: 1, y: 1), "11")] + +block tableTest2: + var t = initTable[string, float]() + t["test"] = 1.2345 + t["111"] = 1.000043 + t["123"] = 1.23 + t.del("111") + + t["012"] = 67.9 + t["123"] = 1.5 # test overwriting + + doAssert t["123"] == 1.5 + try: + echo t["111"] # deleted + except KeyError: + discard + doAssert(not hasKey(t, "111")) + + doAssert "123" in t + doAssert("111" notin t) + + for key, val in items(data): t[key] = val.toFloat + for key, val in items(data): doAssert t[key] == val.toFloat + + doAssert(not t.hasKeyOrPut("456", 4.0)) # test absent key + doAssert t.hasKeyOrPut("012", 3.0) # test present key + var x = t.mgetOrPut("111", 1.5) # test absent key + x = x * 2 + doAssert x == 3.0 + x = t.mgetOrPut("test", 1.5) # test present key + x = x * 2 + doAssert x == 2 * 1.2345 + +block orderedTableTest1: + var t = initOrderedTable[string, int](2) + for key, val in items(data): t[key] = val + for key, val in items(data): doAssert t[key] == val + var i = 0 + # `pairs` needs to yield in insertion order: + for key, val in pairs(t): + doAssert key == data[i][0] + doAssert val == data[i][1] + inc(i) + + for key, val in mpairs(t): val = 99 + for val in mvalues(t): doAssert val == 99 + +block orderedTableTest2: + var + s = initOrderedTable[string, int]() + t = initOrderedTable[string, int]() + doAssert s == t + for key, val in items(data): t[key] = val + doAssert s != t + for key, val in items(sorteddata): s[key] = val + doAssert s != t + t.clear() + doAssert s != t + for key, val in items(sorteddata): t[key] = val + doAssert s == t + +block countTableTest1: + var s = data.toTable + var t = initCountTable[string]() + + for k in s.keys: t.inc(k) + for k in t.keys: doAssert t[k] == 1 + t.inc("90", 3) + t.inc("12", 2) + t.inc("34", 1) + doAssert t.largest()[0] == "90" + + t.sort() + var i = 0 + for k, v in t.pairs: + case i + of 0: doAssert k == "90" and v == 4 + of 1: doAssert k == "12" and v == 3 + of 2: doAssert k == "34" and v == 2 + else: break + inc i + +block countTableTest2: + var + s = initCountTable[int]() + t = initCountTable[int]() + doAssert s == t + s.inc(1) + doAssert s != t + t.inc(2) + doAssert s != t + t.inc(1) + doAssert s != t + s.inc(2) + doAssert s == t + s.inc(1) + doAssert s != t + t.inc(1) + doAssert s == t + +block mpairsTableTest1: + var t = initTable[string, int]() + t["a"] = 1 + t["b"] = 2 + t["c"] = 3 + t["d"] = 4 + for k, v in t.mpairs: + if k == "a" or k == "c": + v = 9 + + for k, v in t.pairs: + if k == "a" or k == "c": + doAssert v == 9 + else: + doAssert v != 1 and v != 3 + +block SyntaxTest: + var x = toTable[int, string]({:}) + +block zeroHashKeysTest: + proc doZeroHashValueTest[T, K, V](t: T, nullHashKey: K, value: V) = + let initialLen = t.len + var testTable = t + testTable[nullHashKey] = value + doAssert testTable[nullHashKey] == value + doAssert testTable.len == initialLen + 1 + testTable.del(nullHashKey) + doAssert testTable.len == initialLen + + # with empty table + doZeroHashValueTest(toTable[int,int]({:}), 0, 42) + doZeroHashValueTest(toTable[string,int]({:}), "", 23) + doZeroHashValueTest(toOrderedTable[int,int]({:}), 0, 42) + doZeroHashValueTest(toOrderedTable[string,int]({:}), "", 23) + + # with non-empty table + doZeroHashValueTest(toTable[int,int]({1:2}), 0, 42) + doZeroHashValueTest(toTable[string,string]({"foo": "bar"}), "", "zero") + doZeroHashValueTest(toOrderedTable[int,int]({3:4}), 0, 42) + doZeroHashValueTest(toOrderedTable[string,string]({"egg": "sausage"}), + "", "spam") + +block clearTableTest: + var t = data.toTable + doAssert t.len() != 0 + t.clear() + doAssert t.len() == 0 + +block clearOrderedTableTest: + var t = data.toOrderedTable + doAssert t.len() != 0 + t.clear() + doAssert t.len() == 0 + +block clearCountTableTest: + var t = initCountTable[string]() + t.inc("90", 3) + t.inc("12", 2) + t.inc("34", 1) + doAssert t.len() != 0 + t.clear() + doAssert t.len() == 0 + +block withKeyTest: + var t: SharedTable[int, int] + t.init() + t.withKey(1) do (k: int, v: var int, pairExists: var bool): + doAssert(v == 0) + pairExists = true + v = 42 + doAssert(t.mget(1) == 42) + t.withKey(1) do (k: int, v: var int, pairExists: var bool): + doAssert(v == 42) + pairExists = false + try: + discard t.mget(1) + doAssert(false, "KeyError expected") + except KeyError: + discard + t.withKey(2) do (k: int, v: var int, pairExists: var bool): + pairExists = false + try: + discard t.mget(2) + doAssert(false, "KeyError expected") + except KeyError: + discard + +block takeTest: + var t = initTable[string, int]() + t["key"] = 123 + + var val = 0 + doAssert(t.take("key", val)) + doAssert(val == 123) + + val = -1 + doAssert(not t.take("key", val)) + doAssert(val == -1) + + doAssert(not t.take("otherkey", val)) + doAssert(val == -1) + +proc orderedTableSortTest() = + var t = initOrderedTable[string, int](2) + for key, val in items(data): t[key] = val + for key, val in items(data): doAssert t[key] == val + t.sort(proc (x, y: tuple[key: string, val: int]): int = cmp(x.key, y.key)) + var i = 0 + # `pairs` needs to yield in sorted order: + for key, val in pairs(t): + doAssert key == sorteddata[i][0] + doAssert val == sorteddata[i][1] + inc(i) + + # check that lookup still works: + for key, val in pairs(t): + doAssert val == t[key] + # check that insert still works: + t["newKeyHere"] = 80 + + +orderedTableSortTest() +echo "true" + |