ttables.nim 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. discard """
  2. output: '''
  3. done tableadds
  4. And we get here
  5. 1
  6. 2
  7. 3
  8. '''
  9. joinable: false
  10. targets: "c cpp js"
  11. """
  12. # xxx wrap in a template to test in VM, see https://github.com/timotheecour/Nim/issues/534#issuecomment-769565033
  13. import hashes, sequtils, tables, algorithm
  14. proc sortedPairs[T](t: T): auto = toSeq(t.pairs).sorted
  15. template sortedItems(t: untyped): untyped = sorted(toSeq(t))
  16. block tableDollar:
  17. # other tests should use `sortedPairs` to be robust to future table/hash
  18. # implementation changes
  19. doAssert ${1: 'a', 2: 'b'}.toTable in ["{1: 'a', 2: 'b'}", "{2: 'b', 1: 'a'}"]
  20. # test should not be joined because it takes too long.
  21. block tableadds:
  22. proc main =
  23. var tab = newTable[string, string]()
  24. for i in 0..1000:
  25. tab["key"] = "value " & $i
  26. main()
  27. echo "done tableadds"
  28. block tcounttable:
  29. # bug #2625
  30. const s_len = 32
  31. var substr_counts: CountTable[string] = initCountTable[string]()
  32. var my_string = "Hello, this is sadly broken for strings over 64 characters. Note that it *does* appear to work for short strings."
  33. for i in 0..(my_string.len - s_len):
  34. let s = my_string[i..i+s_len-1]
  35. substr_counts[s] = 1
  36. # substr_counts[s] = substr_counts[s] + 1 # Also breaks, + 2 as well, etc.
  37. # substr_counts.inc(s) # This works
  38. #echo "Iteration ", i
  39. echo "And we get here"
  40. block thashes:
  41. # Test with int
  42. block:
  43. var t = initTable[int,int]()
  44. t[0] = 42
  45. t[1] = t[0] + 1
  46. doAssert(t[0] == 42)
  47. doAssert(t[1] == 43)
  48. let t2 = {1: 1, 2: 2}.toTable
  49. doAssert(t2[2] == 2)
  50. # Test with char
  51. block:
  52. var t = initTable[char,int]()
  53. t['0'] = 42
  54. t['1'] = t['0'] + 1
  55. doAssert(t['0'] == 42)
  56. doAssert(t['1'] == 43)
  57. let t2 = {'1': 1, '2': 2}.toTable
  58. doAssert(t2['2'] == 2)
  59. # Test with enum
  60. block:
  61. type
  62. E = enum eA, eB, eC
  63. var t = initTable[E,int]()
  64. t[eA] = 42
  65. t[eB] = t[eA] + 1
  66. doAssert(t[eA] == 42)
  67. doAssert(t[eB] == 43)
  68. let t2 = {eA: 1, eB: 2}.toTable
  69. doAssert(t2[eB] == 2)
  70. # Test with range
  71. block:
  72. type
  73. R = range[0..9]
  74. var t = initTable[R,int]() # causes warning, why?
  75. t[1] = 42 # causes warning, why?
  76. t[2] = t[1] + 1
  77. doAssert(t[1] == 42)
  78. doAssert(t[2] == 43)
  79. let t2 = {1.R: 1, 2.R: 2}.toTable
  80. doAssert(t2[2.R] == 2)
  81. # Test which combines the generics for tuples + ordinals
  82. block:
  83. type
  84. E = enum eA, eB, eC
  85. var t = initTable[(string, E, int, char), int]()
  86. t[("a", eA, 0, '0')] = 42
  87. t[("b", eB, 1, '1')] = t[("a", eA, 0, '0')] + 1
  88. doAssert(t[("a", eA, 0, '0')] == 42)
  89. doAssert(t[("b", eB, 1, '1')] == 43)
  90. let t2 = {("a", eA, 0, '0'): 1, ("b", eB, 1, '1'): 2}.toTable
  91. doAssert(t2[("b", eB, 1, '1')] == 2)
  92. # Test to check if overloading is possible
  93. # Unfortunately, this does not seem to work for int
  94. # The same test with a custom hash(s: string) does
  95. # work though.
  96. block:
  97. proc hash(x: int): Hash {.inline.} =
  98. echo "overloaded hash"
  99. result = x
  100. var t = initTable[int, int]()
  101. t[0] = 0
  102. # Check hashability of all integer types (issue #5429)
  103. block:
  104. let intTables = (
  105. newTable[int, string](),
  106. newTable[int8, string](),
  107. newTable[int16, string](),
  108. newTable[int32, string](),
  109. newTable[int64, string](),
  110. newTable[uint, string](),
  111. newTable[uint8, string](),
  112. newTable[uint16, string](),
  113. newTable[uint32, string](),
  114. newTable[uint64, string](),
  115. )
  116. echo "1"
  117. block tindexby:
  118. doAssert indexBy(newSeq[int](), proc(x: int):int = x) == initTable[int, int](), "empty int table"
  119. var tbl1 = initTable[int, int]()
  120. tbl1[1] = 1
  121. tbl1[2] = 2
  122. doAssert indexBy(@[1,2], proc(x: int):int = x) == tbl1, "int table"
  123. type
  124. TElem = object
  125. foo: int
  126. bar: string
  127. let
  128. elem1 = TElem(foo: 1, bar: "bar")
  129. elem2 = TElem(foo: 2, bar: "baz")
  130. var tbl2 = initTable[string, TElem]()
  131. tbl2["bar"] = elem1
  132. tbl2["baz"] = elem2
  133. doAssert indexBy(@[elem1,elem2], proc(x: TElem): string = x.bar) == tbl2, "element table"
  134. block tableconstr:
  135. # Test if the new table constructor syntax works:
  136. template ignoreExpr(e) =
  137. discard
  138. # test first class '..' syntactical citizen:
  139. ignoreExpr x <> 2..4
  140. # test table constructor:
  141. ignoreExpr({:})
  142. ignoreExpr({2: 3, "key": "value"})
  143. # NEW:
  144. doAssert 56 in 50..100
  145. doAssert 56 in 0..60
  146. block ttables2:
  147. proc TestHashIntInt() =
  148. var tab = initTable[int,int]()
  149. let n = 10
  150. for i in 1..n:
  151. tab[i] = i
  152. for i in 1..n:
  153. var x = tab[i]
  154. if x != i : echo "not found ", i
  155. TestHashIntInt()
  156. # bug #2107
  157. var delTab = initTable[int,int](4)
  158. for i in 1..4:
  159. delTab[i] = i
  160. delTab.del(i)
  161. delTab[5] = 5
  162. echo "2"
  163. block tablesref:
  164. const
  165. data = {
  166. "34": 123456, "12": 789,
  167. "90": 343, "0": 34404,
  168. "1": 344004, "2": 344774,
  169. "3": 342244, "4": 3412344,
  170. "5": 341232144, "6": 34214544,
  171. "7": 3434544, "8": 344544,
  172. "9": 34435644, "---00": 346677844,
  173. "10": 34484, "11": 34474, "19": 34464,
  174. "20": 34454, "30": 34141244, "40": 344114,
  175. "50": 344490, "60": 344491, "70": 344492,
  176. "80": 344497}
  177. sorteddata = {
  178. "---00": 346677844,
  179. "0": 34404,
  180. "1": 344004,
  181. "10": 34484,
  182. "11": 34474,
  183. "12": 789,
  184. "19": 34464,
  185. "2": 344774, "20": 34454,
  186. "3": 342244, "30": 34141244,
  187. "34": 123456,
  188. "4": 3412344, "40": 344114,
  189. "5": 341232144, "50": 344490,
  190. "6": 34214544, "60": 344491,
  191. "7": 3434544, "70": 344492,
  192. "8": 344544, "80": 344497,
  193. "9": 34435644,
  194. "90": 343}
  195. block tableTest1:
  196. var t = newTable[tuple[x, y: int], string]()
  197. t[(0,0)] = "00"
  198. t[(1,0)] = "10"
  199. t[(0,1)] = "01"
  200. t[(1,1)] = "11"
  201. for x in 0..1:
  202. for y in 0..1:
  203. doAssert t[(x,y)] == $x & $y
  204. doAssert t.sortedPairs ==
  205. @[((x: 0, y: 0), "00"), ((x: 0, y: 1), "01"), ((x: 1, y: 0), "10"), ((x: 1, y: 1), "11")]
  206. block tableTest2:
  207. var t = newTable[string, float]()
  208. t["test"] = 1.2345
  209. t["111"] = 1.000043
  210. t["123"] = 1.23
  211. t.del("111")
  212. t["012"] = 67.9
  213. t["123"] = 1.5 # test overwriting
  214. doAssert t["123"] == 1.5
  215. try:
  216. echo t["111"] # deleted
  217. except KeyError:
  218. discard
  219. doAssert(not hasKey(t, "111"))
  220. doAssert "111" notin t
  221. for key, val in items(data): t[key] = val.toFloat
  222. for key, val in items(data): doAssert t[key] == val.toFloat
  223. block orderedTableTest1:
  224. var t = newOrderedTable[string, int](2)
  225. for key, val in items(data): t[key] = val
  226. for key, val in items(data): doAssert t[key] == val
  227. var i = 0
  228. # `pairs` needs to yield in insertion order:
  229. for key, val in pairs(t):
  230. doAssert key == data[i][0]
  231. doAssert val == data[i][1]
  232. inc(i)
  233. for key, val in mpairs(t): val = 99
  234. for val in mvalues(t): doAssert val == 99
  235. block countTableTest1:
  236. var s = data.toTable
  237. var t = newCountTable[string]()
  238. var r = newCountTable[string]()
  239. for x in [t, r]:
  240. for k in s.keys:
  241. x.inc(k)
  242. doAssert x[k] == 1
  243. x.inc("90", 3)
  244. x.inc("12", 2)
  245. x.inc("34", 1)
  246. doAssert t.largest()[0] == "90"
  247. t.sort()
  248. r.sort(SortOrder.Ascending)
  249. var ps1 = toSeq t.pairs
  250. var ps2 = toSeq r.pairs
  251. ps2.reverse()
  252. for ps in [ps1, ps2]:
  253. var i = 0
  254. for (k, v) in ps:
  255. case i
  256. of 0: doAssert k == "90" and v == 4
  257. of 1: doAssert k == "12" and v == 3
  258. of 2: doAssert k == "34" and v == 2
  259. else: break
  260. inc i
  261. block smallestLargestNamedFieldsTest: # bug #14918
  262. const a = [7, 8, 8]
  263. proc testNamedFields(t: CountTable | CountTableRef) =
  264. doAssert t.smallest.key == 7
  265. doAssert t.smallest.val == 1
  266. doAssert t.largest.key == 8
  267. doAssert t.largest.val == 2
  268. let t1 = toCountTable(a)
  269. testNamedFields(t1)
  270. let t2 = newCountTable(a)
  271. testNamedFields(t2)
  272. block SyntaxTest:
  273. var x = newTable[int, string]({:})
  274. discard x
  275. block nilTest:
  276. var i, j: TableRef[int, int] = nil
  277. doAssert i == j
  278. j = newTable[int, int]()
  279. doAssert i != j
  280. doAssert j != i
  281. i = newTable[int, int]()
  282. doAssert i == j
  283. proc orderedTableSortTest() =
  284. var t = newOrderedTable[string, int](2)
  285. for key, val in items(data): t[key] = val
  286. for key, val in items(data): doAssert t[key] == val
  287. proc cmper(x, y: tuple[key: string, val: int]): int = cmp(x.key, y.key)
  288. t.sort(cmper)
  289. var i = 0
  290. # `pairs` needs to yield in sorted order:
  291. for key, val in pairs(t):
  292. doAssert key == sorteddata[i][0]
  293. doAssert val == sorteddata[i][1]
  294. inc(i)
  295. t.sort(cmper, order=SortOrder.Descending)
  296. i = 0
  297. for key, val in pairs(t):
  298. doAssert key == sorteddata[high(data)-i][0]
  299. doAssert val == sorteddata[high(data)-i][1]
  300. inc(i)
  301. # check that lookup still works:
  302. for key, val in pairs(t):
  303. doAssert val == t[key]
  304. # check that insert still works:
  305. t["newKeyHere"] = 80
  306. block anonZipTest:
  307. let keys = @['a','b','c']
  308. let values = @[1, 2, 3]
  309. doAssert zip(keys, values).toTable.sortedPairs == @[('a', 1), ('b', 2), ('c', 3)]
  310. block clearTableTest:
  311. var t = newTable[string, float]()
  312. t["test"] = 1.2345
  313. t["111"] = 1.000043
  314. t["123"] = 1.23
  315. doAssert t.len() != 0
  316. t.clear()
  317. doAssert t.len() == 0
  318. block clearOrderedTableTest:
  319. var t = newOrderedTable[string, int](2)
  320. for key, val in items(data): t[key] = val
  321. doAssert t.len() != 0
  322. t.clear()
  323. doAssert t.len() == 0
  324. block clearCountTableTest:
  325. var t = newCountTable[string]()
  326. t.inc("90", 3)
  327. t.inc("12", 2)
  328. t.inc("34", 1)
  329. doAssert t.len() != 0
  330. t.clear()
  331. doAssert t.len() == 0
  332. orderedTableSortTest()
  333. echo "3"
  334. block: # https://github.com/nim-lang/Nim/issues/13496
  335. template testDel(body) =
  336. block:
  337. body
  338. when t is CountTable|CountTableRef:
  339. t.inc(15, 1)
  340. t.inc(19, 2)
  341. t.inc(17, 3)
  342. t.inc(150, 4)
  343. t.del(150)
  344. else:
  345. t[15] = 1
  346. t[19] = 2
  347. t[17] = 3
  348. t[150] = 4
  349. t.del(150)
  350. doAssert t.len == 3
  351. doAssert sortedItems(t.values) == @[1, 2, 3]
  352. doAssert sortedItems(t.keys) == @[15, 17, 19]
  353. doAssert sortedPairs(t) == @[(15, 1), (17, 3), (19, 2)]
  354. var s = newSeq[int]()
  355. for v in t.values: s.add(v)
  356. doAssert s.len == 3
  357. doAssert sortedItems(s) == @[1, 2, 3]
  358. when t is OrderedTable|OrderedTableRef:
  359. doAssert toSeq(t.keys) == @[15, 19, 17]
  360. doAssert toSeq(t.values) == @[1,2,3]
  361. doAssert toSeq(t.pairs) == @[(15, 1), (19, 2), (17, 3)]
  362. testDel(): (var t: Table[int, int])
  363. testDel(): (let t = newTable[int, int]())
  364. testDel(): (var t: OrderedTable[int, int])
  365. testDel(): (let t = newOrderedTable[int, int]())
  366. testDel(): (var t: CountTable[int])
  367. testDel(): (let t = newCountTable[int]())
  368. block testNonPowerOf2:
  369. var a = initTable[int, int](7)
  370. a[1] = 10
  371. doAssert a[1] == 10
  372. var b = initTable[int, int](9)
  373. b[1] = 10
  374. doAssert b[1] == 10
  375. block emptyOrdered:
  376. var t1: OrderedTable[int, string]
  377. var t2: OrderedTable[int, string]
  378. doAssert t1 == t2
  379. block: # Table[ref, int]
  380. type A = ref object
  381. x: int
  382. var t: OrderedTable[A, int]
  383. let a1 = A(x: 3)
  384. let a2 = A(x: 3)
  385. t[a1] = 10
  386. t[a2] = 11
  387. doAssert t[a1] == 10
  388. doAssert t[a2] == 11