ttables.nim 11 KB

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