tnimgrep.nim 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. discard """
  2. output: '''
  3. [Suite] nimgrep filesystem
  4. [Suite] nimgrep contents filtering
  5. '''
  6. """
  7. ## Authors: quantimnot, a-mr
  8. import std/[osproc, os, streams, unittest, strutils]
  9. import std/syncio
  10. #=======
  11. # setup
  12. #=======
  13. var process: Process
  14. var ngStdOut, ngStdErr: string
  15. var ngExitCode: int
  16. let previousDir = getCurrentDir()
  17. let tempDir = getTempDir()
  18. let testFilesRoot = tempDir / "nimgrep_test_files"
  19. template nimgrep(optsAndArgs): untyped =
  20. process = startProcess(previousDir / "bin/nimgrep " & optsAndArgs,
  21. options = {poEvalCommand})
  22. ngExitCode = process.waitForExit
  23. ngStdOut = process.outputStream.readAll
  24. ngStdErr = process.errorStream.readAll
  25. func fixSlash(s: string): string =
  26. if DirSep == '/':
  27. result = s
  28. else: # on Windows
  29. result = s.replace('/', DirSep)
  30. func initString(len = 1000, val = ' '): string =
  31. result = newString(len)
  32. for i in 0..<len:
  33. result[i] = val
  34. # Create test file hierarchy.
  35. createDir testFilesRoot
  36. setCurrentDir testFilesRoot
  37. createDir "a" / "b"
  38. createDir "c" / "b"
  39. createDir ".hidden"
  40. writeFile("do_not_create_another_file_with_this_pattern_KJKJHSFSFKASHFBKAF", "PATTERN")
  41. writeFile("a" / "b" / "only_the_pattern", "PATTERN")
  42. writeFile("c" / "b" / "only_the_pattern", "PATTERN")
  43. writeFile(".hidden" / "only_the_pattern", "PATTERN")
  44. writeFile("null_in_first_1k", "\0PATTERN")
  45. writeFile("null_after_first_1k", initString(1000) & "\0")
  46. writeFile("empty", "")
  47. writeFile("context_match_filtering", """
  48. -
  49. CONTEXTPAT
  50. -
  51. PATTERN
  52. -
  53. -
  54. -
  55. -
  56. -
  57. -
  58. PATTERN
  59. -
  60. -
  61. -
  62. """)
  63. writeFile("only_the_pattern.txt", "PATTERN")
  64. writeFile("only_the_pattern.ascii", "PATTERN")
  65. #=======
  66. # tests
  67. #=======
  68. suite "nimgrep filesystem":
  69. test "`--filename` with matching file":
  70. nimgrep "-r --filename:KJKJHSFSFKASHFBKAF PATTERN"
  71. check ngExitCode == 0
  72. check ngStdErr.len == 0
  73. check ngStdOut == fixSlash dedent"""
  74. ./do_not_create_another_file_with_this_pattern_KJKJHSFSFKASHFBKAF:1: PATTERN
  75. 1 matches
  76. """
  77. test "`--dirname` with matching dir":
  78. nimgrep "-r --dirname:.hid PATTERN"
  79. check ngExitCode == 0
  80. check ngStdErr.len == 0
  81. check ngStdOut == fixSlash dedent"""
  82. .hidden/only_the_pattern:1: PATTERN
  83. 1 matches
  84. """
  85. let only_the_pattern = fixSlash dedent"""
  86. a/b/only_the_pattern:1: PATTERN
  87. c/b/only_the_pattern:1: PATTERN
  88. 2 matches
  89. """
  90. let only_a = fixSlash dedent"""
  91. a/b/only_the_pattern:1: PATTERN
  92. 1 matches
  93. """
  94. test "`--dirname` with matching grandparent path segment":
  95. nimgrep "-r --dirname:a PATTERN"
  96. check ngExitCode == 0
  97. check ngStdErr.len == 0
  98. check ngStdOut == only_a
  99. test "`--dirpath` with matching grandparent path segment":
  100. nimgrep "-r --dirp:a PATTERN"
  101. check ngExitCode == 0
  102. check ngStdErr.len == 0
  103. check ngStdOut == only_a
  104. test "`--dirpath` with matching grandparent path segment":
  105. nimgrep "-r --dirpath:a/b PATTERN".fixSlash
  106. check ngExitCode == 0
  107. check ngStdErr.len == 0
  108. check ngStdOut == only_a
  109. test "`--dirname` with matching parent path segment":
  110. nimgrep "-r --dirname:b PATTERN"
  111. check ngExitCode == 0
  112. check ngStdErr.len == 0
  113. check ngStdOut == only_the_pattern
  114. test "`--dirpath` with matching parent path segment":
  115. nimgrep "-r --dirpath:b PATTERN"
  116. check ngExitCode == 0
  117. check ngStdErr.len == 0
  118. check ngStdOut == only_the_pattern
  119. let patterns_without_directory_a_b = fixSlash dedent"""
  120. ./context_match_filtering:4: PATTERN
  121. ./context_match_filtering:12: PATTERN
  122. ./do_not_create_another_file_with_this_pattern_KJKJHSFSFKASHFBKAF:1: PATTERN
  123. ./null_in_first_1k:1: """ & "\0PATTERN\n" & dedent"""
  124. ./only_the_pattern.ascii:1: PATTERN
  125. ./only_the_pattern.txt:1: PATTERN
  126. .hidden/only_the_pattern:1: PATTERN
  127. c/b/only_the_pattern:1: PATTERN
  128. 8 matches
  129. """
  130. let patterns_without_directory_b = fixSlash dedent"""
  131. ./context_match_filtering:4: PATTERN
  132. ./context_match_filtering:12: PATTERN
  133. ./do_not_create_another_file_with_this_pattern_KJKJHSFSFKASHFBKAF:1: PATTERN
  134. ./null_in_first_1k:1: """ & "\0PATTERN\n" & dedent"""
  135. ./only_the_pattern.ascii:1: PATTERN
  136. ./only_the_pattern.txt:1: PATTERN
  137. .hidden/only_the_pattern:1: PATTERN
  138. 7 matches
  139. """
  140. test "`--ndirname` not matching grandparent path segment":
  141. nimgrep "-r --ndirname:a PATTERN"
  142. check ngExitCode == 0
  143. check ngStdErr.len == 0
  144. check ngStdOut == patterns_without_directory_a_b
  145. test "`--ndirname` not matching parent path segment":
  146. nimgrep "-r --ndirname:b PATTERN"
  147. check ngExitCode == 0
  148. check ngStdErr.len == 0
  149. check ngStdOut == patterns_without_directory_b
  150. test "`--notdirpath` not matching grandparent path segment":
  151. nimgrep "-r --notdirpath:a PATTERN"
  152. check ngExitCode == 0
  153. check ngStdErr.len == 0
  154. check ngStdOut == patterns_without_directory_a_b
  155. test "`--notdirpath` not matching parent path segment":
  156. nimgrep "-r --ndirp:b PATTERN"
  157. check ngExitCode == 0
  158. check ngStdErr.len == 0
  159. check ngStdOut == patterns_without_directory_b
  160. test "`--notdirpath` with matching grandparent/parent path segment":
  161. nimgrep "-r --ndirp:a/b PATTERN".fixSlash
  162. check ngExitCode == 0
  163. check ngStdErr.len == 0
  164. check ngStdOut == patterns_without_directory_a_b
  165. test "`--text`, `-t`, `--bin:off` with file containing a null in first 1k chars":
  166. nimgrep "-r --text PATTERN null_in_first_1k"
  167. check ngExitCode == 0
  168. check ngStdErr.len == 0
  169. check ngStdOut == "0 matches\n"
  170. checkpoint "`--text`"
  171. nimgrep "-r -t PATTERN null_in_first_1k"
  172. check ngExitCode == 0
  173. check ngStdErr.len == 0
  174. check ngStdOut == "0 matches\n"
  175. checkpoint "`-t`"
  176. nimgrep "-r --bin:off PATTERN null_in_first_1k"
  177. check ngExitCode == 0
  178. check ngStdErr.len == 0
  179. check ngStdOut == "0 matches\n"
  180. checkpoint "`--binary:off`"
  181. test "`--bin:only` with file containing a null in first 1k chars":
  182. nimgrep "--bin:only -@ PATTERN null_in_first_1k null_after_first_1k only_the_pattern.txt"
  183. check ngExitCode == 0
  184. check ngStdErr.len == 0
  185. check ngStdOut == dedent"""
  186. null_in_first_1k:1: ^@PATTERN
  187. 1 matches
  188. """
  189. test "`--bin:only` with file containing a null after first 1k chars":
  190. nimgrep "--bin:only PATTERN null_after_first_1k only_the_pattern.txt"
  191. check ngExitCode == 0
  192. check ngStdErr.len == 0
  193. check ngStdOut == "0 matches\n"
  194. # TODO: we need to throw a warning if e.g. both extension was provided and
  195. # inappropriate filename was directly provided via command line
  196. #
  197. # test "`--ext:doesnotexist` without a matching file":
  198. # # skip() # FIXME: this test fails
  199. # nimgrep "--ext:doesnotexist PATTERN context_match_filtering only_the_pattern.txt"
  200. # check ngExitCode == 0
  201. # check ngStdErr.len == 0
  202. # check ngStdOut == """
  203. #0 matches
  204. #"""
  205. #
  206. #
  207. # test "`--ext:txt` with a matching file":
  208. # nimgrep "--ext:txt PATTERN context_match_filtering only_the_pattern.txt"
  209. # check ngExitCode == 0
  210. # check ngStdErr.len == 0
  211. # check ngStdOut == """
  212. #only_the_pattern.txt:1: PATTERN
  213. #1 matches
  214. #"""
  215. #
  216. #
  217. # test "`--ext:txt|doesnotexist` with some matching files":
  218. # nimgrep "--ext:txt|doesnotexist PATTERN context_match_filtering only_the_pattern.txt only_the_pattern.ascii"
  219. # check ngExitCode == 0
  220. # check ngStdErr.len == 0
  221. # check ngStdOut == """
  222. #only_the_pattern.txt:1: PATTERN
  223. #1 matches
  224. #"""
  225. #
  226. #
  227. # test "`--ext` with some matching files":
  228. # nimgrep "--ext PATTERN context_match_filtering only_the_pattern.txt only_the_pattern.ascii"
  229. # check ngExitCode == 0
  230. # check ngStdErr.len == 0
  231. # check ngStdOut == """
  232. #context_match_filtering:4: PATTERN
  233. #context_match_filtering:12: PATTERN
  234. #2 matches
  235. #"""
  236. #
  237. #
  238. # test "`--ext:txt --ext` with some matching files":
  239. # nimgrep "--ext:txt --ext PATTERN context_match_filtering only_the_pattern.txt only_the_pattern.ascii"
  240. # check ngExitCode == 0
  241. # check ngStdErr.len == 0
  242. # check ngStdOut == """
  243. #context_match_filtering:4: PATTERN
  244. #context_match_filtering:12: PATTERN
  245. #only_the_pattern.txt:1: PATTERN
  246. #3 matches
  247. #"""
  248. suite "nimgrep contents filtering":
  249. test "`--inFile` with matching file":
  250. nimgrep "-r --inf:CONTEXTPAT PATTERN"
  251. check ngExitCode == 0
  252. check ngStdErr.len == 0
  253. check ngStdOut == fixSlash dedent"""
  254. ./context_match_filtering:4: PATTERN
  255. ./context_match_filtering:12: PATTERN
  256. 2 matches
  257. """
  258. test "`--notinFile` with matching files":
  259. nimgrep "-r --ninf:CONTEXTPAT PATTERN"
  260. check ngExitCode == 0
  261. check ngStdErr.len == 0
  262. check ngStdOut == fixSlash dedent"""
  263. ./do_not_create_another_file_with_this_pattern_KJKJHSFSFKASHFBKAF:1: PATTERN
  264. ./null_in_first_1k:1: """ & "\0PATTERN\n" & dedent"""
  265. ./only_the_pattern.ascii:1: PATTERN
  266. ./only_the_pattern.txt:1: PATTERN
  267. .hidden/only_the_pattern:1: PATTERN
  268. a/b/only_the_pattern:1: PATTERN
  269. c/b/only_the_pattern:1: PATTERN
  270. 7 matches
  271. """
  272. test "`--inContext` with missing context option":
  273. # Using `--inContext` implies default -c:1 is used
  274. nimgrep "-r --inContext:CONTEXTPAT PATTERN"
  275. check ngExitCode == 0
  276. check ngStdErr.len == 0
  277. check ngStdOut == "0 matches\n"
  278. test "`--inContext` with PAT matching PATTERN":
  279. # This tests the scenario where PAT always matches PATTERN and thus
  280. # has the same effect as excluding the `inContext` option.
  281. # I'm not sure of the desired behaviour here.
  282. nimgrep "--context:2 --inc:PAT PATTERN context_match_filtering"
  283. check ngExitCode == 0
  284. check ngStdErr.len == 0
  285. check ngStdOut == dedent"""
  286. context_match_filtering:2 CONTEXTPAT
  287. context_match_filtering:3 -
  288. context_match_filtering:4: PATTERN
  289. context_match_filtering:5 -
  290. context_match_filtering:6 -
  291. context_match_filtering:10 -
  292. context_match_filtering:11 -
  293. context_match_filtering:12: PATTERN
  294. context_match_filtering:13 -
  295. context_match_filtering:14 -
  296. 2 matches
  297. """
  298. test "`--inContext` with PAT in context":
  299. nimgrep "--context:2 --inContext:CONTEXTPAT PATTERN context_match_filtering"
  300. check ngExitCode == 0
  301. check ngStdErr.len == 0
  302. check ngStdOut == dedent"""
  303. context_match_filtering:2 CONTEXTPAT
  304. context_match_filtering:3 -
  305. context_match_filtering:4: PATTERN
  306. context_match_filtering:5 -
  307. context_match_filtering:6 -
  308. 1 matches
  309. """
  310. test "`--notinContext` with PAT matching some contexts":
  311. nimgrep "--context:2 --ninContext:CONTEXTPAT PATTERN context_match_filtering"
  312. check ngExitCode == 0
  313. check ngStdErr.len == 0
  314. check ngStdOut == dedent"""
  315. context_match_filtering:10 -
  316. context_match_filtering:11 -
  317. context_match_filtering:12: PATTERN
  318. context_match_filtering:13 -
  319. context_match_filtering:14 -
  320. 1 matches
  321. """
  322. test "`--notinContext` with PAT not matching any of the contexts":
  323. nimgrep "--context:1 --ninc:CONTEXTPAT PATTERN context_match_filtering"
  324. check ngExitCode == 0
  325. check ngStdErr.len == 0
  326. check ngStdOut == dedent"""
  327. context_match_filtering:3 -
  328. context_match_filtering:4: PATTERN
  329. context_match_filtering:5 -
  330. context_match_filtering:11 -
  331. context_match_filtering:12: PATTERN
  332. context_match_filtering:13 -
  333. 2 matches
  334. """
  335. #=========
  336. # cleanup
  337. #=========
  338. setCurrentDir previousDir
  339. removeDir testFilesRoot