tos.nim 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. discard """
  2. output: '''
  3. All:
  4. __really_obscure_dir_name/are.x
  5. __really_obscure_dir_name/created
  6. __really_obscure_dir_name/dirs
  7. __really_obscure_dir_name/files.q
  8. __really_obscure_dir_name/some
  9. __really_obscure_dir_name/test
  10. __really_obscure_dir_name/testing.r
  11. __really_obscure_dir_name/these.txt
  12. Files:
  13. __really_obscure_dir_name/are.x
  14. __really_obscure_dir_name/files.q
  15. __really_obscure_dir_name/testing.r
  16. __really_obscure_dir_name/these.txt
  17. Dirs:
  18. __really_obscure_dir_name/created
  19. __really_obscure_dir_name/dirs
  20. __really_obscure_dir_name/some
  21. __really_obscure_dir_name/test
  22. Raises
  23. Raises
  24. '''
  25. joinable: false
  26. """
  27. # test os path creation, iteration, and deletion
  28. import os, strutils, pathnorm
  29. from stdtest/specialpaths import buildDir
  30. block fileOperations:
  31. let files = @["these.txt", "are.x", "testing.r", "files.q"]
  32. let dirs = @["some", "created", "test", "dirs"]
  33. let dname = "__really_obscure_dir_name"
  34. createDir(dname)
  35. doAssert dirExists(dname)
  36. block: # copyFile, copyFileToDir
  37. doAssertRaises(OSError): copyFile(dname/"nonexistent.txt", dname/"nonexistent.txt")
  38. let fname = "D20201009T112235"
  39. let fname2 = "D20201009T112235.2"
  40. let str = "foo1\0foo2\nfoo3\0"
  41. let file = dname/fname
  42. let file2 = dname/fname2
  43. writeFile(file, str)
  44. doAssert readFile(file) == str
  45. let sub = "sub"
  46. doAssertRaises(OSError): copyFile(file, dname/sub/fname2)
  47. doAssertRaises(OSError): copyFileToDir(file, dname/sub)
  48. doAssertRaises(ValueError): copyFileToDir(file, "")
  49. copyFile(file, file2)
  50. doAssert fileExists(file2)
  51. doAssert readFile(file2) == str
  52. createDir(dname/sub)
  53. copyFileToDir(file, dname/sub)
  54. doAssert fileExists(dname/sub/fname)
  55. removeDir(dname/sub)
  56. doAssert not dirExists(dname/sub)
  57. removeFile(file)
  58. removeFile(file2)
  59. # Test creating files and dirs
  60. for dir in dirs:
  61. createDir(dname/dir)
  62. doAssert dirExists(dname/dir)
  63. for file in files:
  64. let fh = open(dname/file, fmReadWrite)
  65. fh.close()
  66. doAssert fileExists(dname/file)
  67. echo "All:"
  68. template norm(x): untyped =
  69. (when defined(windows): x.replace('\\', '/') else: x)
  70. for path in walkPattern(dname/"*"):
  71. echo path.norm
  72. echo "Files:"
  73. for path in walkFiles(dname/"*"):
  74. echo path.norm
  75. echo "Dirs:"
  76. for path in walkDirs(dname/"*"):
  77. echo path.norm
  78. # Test removal of files dirs
  79. for dir in dirs:
  80. removeDir(dname/dir)
  81. doAssert: not dirExists(dname/dir)
  82. for file in files:
  83. removeFile(dname/file)
  84. doAssert: not fileExists(dname/file)
  85. removeDir(dname)
  86. doAssert: not dirExists(dname)
  87. # createDir should create recursive directories
  88. createDir(dirs[0] / dirs[1])
  89. doAssert dirExists(dirs[0] / dirs[1]) # true
  90. removeDir(dirs[0])
  91. # createDir should properly handle trailing separator
  92. createDir(dname / "")
  93. doAssert dirExists(dname) # true
  94. removeDir(dname)
  95. # createDir should raise IOError if the path exists
  96. # and is not a directory
  97. open(dname, fmWrite).close
  98. try:
  99. createDir(dname)
  100. except IOError:
  101. echo "Raises"
  102. removeFile(dname)
  103. # removeFile should not remove directory
  104. createDir(dname)
  105. try:
  106. removeFile(dname)
  107. except OSError:
  108. echo "Raises"
  109. removeDir(dname)
  110. # test copyDir:
  111. createDir("a/b")
  112. open("a/b/file.txt", fmWrite).close
  113. createDir("a/b/c")
  114. open("a/b/c/fileC.txt", fmWrite).close
  115. copyDir("a", "../dest/a")
  116. removeDir("a")
  117. doAssert dirExists("../dest/a/b")
  118. doAssert fileExists("../dest/a/b/file.txt")
  119. doAssert fileExists("../dest/a/b/c/fileC.txt")
  120. removeDir("../dest")
  121. # test copyDir:
  122. # if separator at the end of a path
  123. createDir("a/b")
  124. open("a/file.txt", fmWrite).close
  125. copyDir("a/", "../dest/a/")
  126. removeDir("a")
  127. doAssert dirExists("../dest/a/b")
  128. doAssert fileExists("../dest/a/file.txt")
  129. removeDir("../dest")
  130. # Symlink handling in `copyFile`, `copyFileWithPermissions`, `copyFileToDir`,
  131. # `copyDir`, `copyDirWithPermissions`, `moveFile`, and `moveDir`.
  132. block:
  133. const symlinksAreHandled = not defined(windows)
  134. const dname = buildDir/"D20210116T140629"
  135. const subDir = dname/"sub"
  136. const subDir2 = dname/"sub2"
  137. const brokenSymlinkName = "D20210101T191320_BROKEN_SYMLINK"
  138. const brokenSymlink = dname/brokenSymlinkName
  139. const brokenSymlinkSrc = "D20210101T191320_nonexistent"
  140. const brokenSymlinkCopy = brokenSymlink & "_COPY"
  141. const brokenSymlinkInSubDir = subDir/brokenSymlinkName
  142. const brokenSymlinkInSubDir2 = subDir2/brokenSymlinkName
  143. createDir(subDir)
  144. createSymlink(brokenSymlinkSrc, brokenSymlink)
  145. # Test copyFile
  146. when symlinksAreHandled:
  147. doAssertRaises(OSError):
  148. copyFile(brokenSymlink, brokenSymlinkCopy)
  149. doAssertRaises(OSError):
  150. copyFile(brokenSymlink, brokenSymlinkCopy, {cfSymlinkFollow})
  151. copyFile(brokenSymlink, brokenSymlinkCopy, {cfSymlinkIgnore})
  152. doAssert not fileExists(brokenSymlinkCopy)
  153. copyFile(brokenSymlink, brokenSymlinkCopy, {cfSymlinkAsIs})
  154. when symlinksAreHandled:
  155. doAssert expandSymlink(brokenSymlinkCopy) == brokenSymlinkSrc
  156. removeFile(brokenSymlinkCopy)
  157. else:
  158. doAssert not fileExists(brokenSymlinkCopy)
  159. doAssertRaises(AssertionDefect):
  160. copyFile(brokenSymlink, brokenSymlinkCopy,
  161. {cfSymlinkAsIs, cfSymlinkFollow})
  162. # Test copyFileWithPermissions
  163. when symlinksAreHandled:
  164. doAssertRaises(OSError):
  165. copyFileWithPermissions(brokenSymlink, brokenSymlinkCopy)
  166. doAssertRaises(OSError):
  167. copyFileWithPermissions(brokenSymlink, brokenSymlinkCopy,
  168. options = {cfSymlinkFollow})
  169. copyFileWithPermissions(brokenSymlink, brokenSymlinkCopy,
  170. options = {cfSymlinkIgnore})
  171. doAssert not fileExists(brokenSymlinkCopy)
  172. copyFileWithPermissions(brokenSymlink, brokenSymlinkCopy,
  173. options = {cfSymlinkAsIs})
  174. when symlinksAreHandled:
  175. doAssert expandSymlink(brokenSymlinkCopy) == brokenSymlinkSrc
  176. removeFile(brokenSymlinkCopy)
  177. else:
  178. doAssert not fileExists(brokenSymlinkCopy)
  179. doAssertRaises(AssertionDefect):
  180. copyFileWithPermissions(brokenSymlink, brokenSymlinkCopy,
  181. options = {cfSymlinkAsIs, cfSymlinkFollow})
  182. # Test copyFileToDir
  183. when symlinksAreHandled:
  184. doAssertRaises(OSError):
  185. copyFileToDir(brokenSymlink, subDir)
  186. doAssertRaises(OSError):
  187. copyFileToDir(brokenSymlink, subDir, {cfSymlinkFollow})
  188. copyFileToDir(brokenSymlink, subDir, {cfSymlinkIgnore})
  189. doAssert not fileExists(brokenSymlinkInSubDir)
  190. copyFileToDir(brokenSymlink, subDir, {cfSymlinkAsIs})
  191. when symlinksAreHandled:
  192. doAssert expandSymlink(brokenSymlinkInSubDir) == brokenSymlinkSrc
  193. removeFile(brokenSymlinkInSubDir)
  194. else:
  195. doAssert not fileExists(brokenSymlinkInSubDir)
  196. createSymlink(brokenSymlinkSrc, brokenSymlinkInSubDir)
  197. # Test copyDir
  198. copyDir(subDir, subDir2)
  199. when symlinksAreHandled:
  200. doAssert expandSymlink(brokenSymlinkInSubDir2) == brokenSymlinkSrc
  201. else:
  202. doAssert not fileExists(brokenSymlinkInSubDir2)
  203. removeDir(subDir2)
  204. # Test copyDirWithPermissions
  205. copyDirWithPermissions(subDir, subDir2)
  206. when symlinksAreHandled:
  207. doAssert expandSymlink(brokenSymlinkInSubDir2) == brokenSymlinkSrc
  208. else:
  209. doAssert not fileExists(brokenSymlinkInSubDir2)
  210. removeDir(subDir2)
  211. # Test moveFile
  212. moveFile(brokenSymlink, brokenSymlinkCopy)
  213. when not defined(windows):
  214. doAssert expandSymlink(brokenSymlinkCopy) == brokenSymlinkSrc
  215. else:
  216. doAssert symlinkExists(brokenSymlinkCopy)
  217. removeFile(brokenSymlinkCopy)
  218. # Test moveDir
  219. moveDir(subDir, subDir2)
  220. when not defined(windows):
  221. doAssert expandSymlink(brokenSymlinkInSubDir2) == brokenSymlinkSrc
  222. else:
  223. doAssert symlinkExists(brokenSymlinkInSubDir2)
  224. removeDir(dname)
  225. block: # moveFile
  226. let tempDir = getTempDir() / "D20210609T151608"
  227. createDir(tempDir)
  228. defer: removeDir(tempDir)
  229. writeFile(tempDir / "a.txt", "")
  230. moveFile(tempDir / "a.txt", tempDir / "b.txt")
  231. doAssert not fileExists(tempDir / "a.txt")
  232. doAssert fileExists(tempDir / "b.txt")
  233. removeFile(tempDir / "b.txt")
  234. createDir(tempDir / "moveFile_test")
  235. writeFile(tempDir / "moveFile_test/a.txt", "")
  236. moveFile(tempDir / "moveFile_test/a.txt", tempDir / "moveFile_test/b.txt")
  237. doAssert not fileExists(tempDir / "moveFile_test/a.txt")
  238. doAssert fileExists(tempDir / "moveFile_test/b.txt")
  239. removeDir(tempDir / "moveFile_test")
  240. createDir(tempDir / "moveFile_test")
  241. writeFile(tempDir / "a.txt", "")
  242. moveFile(tempDir / "a.txt", tempDir / "moveFile_test/b.txt")
  243. doAssert not fileExists(tempDir / "a.txt")
  244. doAssert fileExists(tempDir / "moveFile_test/b.txt")
  245. removeDir(tempDir / "moveFile_test")
  246. block: # moveDir
  247. let tempDir = getTempDir() / "D20210609T161443"
  248. createDir(tempDir)
  249. defer: removeDir(tempDir)
  250. createDir(tempDir / "moveDir_test")
  251. moveDir(tempDir / "moveDir_test/", tempDir / "moveDir_test_dest")
  252. doAssert not dirExists(tempDir / "moveDir_test")
  253. doAssert dirExists(tempDir / "moveDir_test_dest")
  254. removeDir(tempDir / "moveDir_test_dest")
  255. createDir(tempDir / "moveDir_test")
  256. writeFile(tempDir / "moveDir_test/a.txt", "")
  257. moveDir(tempDir / "moveDir_test", tempDir / "moveDir_test_dest")
  258. doAssert not dirExists(tempDir / "moveDir_test")
  259. doAssert not fileExists(tempDir / "moveDir_test/a.txt")
  260. doAssert dirExists(tempDir / "moveDir_test_dest")
  261. doAssert fileExists(tempDir / "moveDir_test_dest/a.txt")
  262. removeDir(tempDir / "moveDir_test_dest")
  263. import times
  264. block modificationTime:
  265. # Test get/set modification times
  266. # Should support at least microsecond resolution
  267. let tm = fromUnix(0) + 100.microseconds
  268. writeFile("a", "")
  269. setLastModificationTime("a", tm)
  270. when defined(macosx):
  271. doAssert true
  272. else:
  273. doAssert getLastModificationTime("a") == tm
  274. removeFile("a")
  275. block walkDirRec:
  276. createDir("walkdir_test/a/b")
  277. open("walkdir_test/a/b/file_1", fmWrite).close()
  278. open("walkdir_test/a/file_2", fmWrite).close()
  279. for p in walkDirRec("walkdir_test"):
  280. doAssert p.fileExists
  281. doAssert p.startsWith("walkdir_test")
  282. var s: seq[string]
  283. for p in walkDirRec("walkdir_test", {pcFile}, {pcDir}, relative = true):
  284. s.add(p)
  285. doAssert s.len == 2
  286. doAssert "a" / "b" / "file_1" in s
  287. doAssert "a" / "file_2" in s
  288. removeDir("walkdir_test")
  289. block: # walkDir
  290. doAssertRaises(OSError):
  291. for a in walkDir("nonexistent", checkDir = true): discard
  292. doAssertRaises(OSError):
  293. for p in walkDirRec("nonexistent", checkDir = true): discard
  294. when not defined(windows):
  295. block walkDirRelative:
  296. createDir("walkdir_test")
  297. createSymlink(".", "walkdir_test/c")
  298. for k, p in walkDir("walkdir_test", true):
  299. doAssert k == pcLinkToDir
  300. removeDir("walkdir_test")
  301. block normalizedPath:
  302. doAssert normalizedPath("") == ""
  303. block relative:
  304. doAssert normalizedPath(".") == "."
  305. doAssert normalizedPath("foo/..") == "."
  306. doAssert normalizedPath("foo//../bar/.") == "bar"
  307. doAssert normalizedPath("..") == ".."
  308. doAssert normalizedPath("../") == ".."
  309. doAssert normalizedPath("../..") == unixToNativePath"../.."
  310. doAssert normalizedPath("../a/..") == ".."
  311. doAssert normalizedPath("../a/../") == ".."
  312. doAssert normalizedPath("./") == "."
  313. block absolute:
  314. doAssert normalizedPath("/") == unixToNativePath"/"
  315. doAssert normalizedPath("/.") == unixToNativePath"/"
  316. doAssert normalizedPath("/..") == unixToNativePath"/.."
  317. doAssert normalizedPath("/../") == unixToNativePath"/.."
  318. doAssert normalizedPath("/../..") == unixToNativePath"/../.."
  319. doAssert normalizedPath("/../../") == unixToNativePath"/../.."
  320. doAssert normalizedPath("/../../../") == unixToNativePath"/../../.."
  321. doAssert normalizedPath("/a/b/../../foo") == unixToNativePath"/foo"
  322. doAssert normalizedPath("/a/b/../../../foo") == unixToNativePath"/../foo"
  323. doAssert normalizedPath("/./") == unixToNativePath"/"
  324. doAssert normalizedPath("//") == unixToNativePath"/"
  325. doAssert normalizedPath("///") == unixToNativePath"/"
  326. doAssert normalizedPath("/a//b") == unixToNativePath"/a/b"
  327. doAssert normalizedPath("/a///b") == unixToNativePath"/a/b"
  328. doAssert normalizedPath("/a/b/c/..") == unixToNativePath"/a/b"
  329. doAssert normalizedPath("/a/b/c/../") == unixToNativePath"/a/b"
  330. block isHidden:
  331. when defined(posix):
  332. doAssert ".foo.txt".isHidden
  333. doAssert "bar/.foo.ext".isHidden
  334. doAssert not "bar".isHidden
  335. doAssert not "foo/".isHidden
  336. doAssert ".foo/.".isHidden
  337. # Corner cases: `isHidden` is not yet `..` aware
  338. doAssert not ".foo/..".isHidden
  339. block absolutePath:
  340. doAssertRaises(ValueError): discard absolutePath("a", "b")
  341. doAssert absolutePath("a") == getCurrentDir() / "a"
  342. doAssert absolutePath("a", "/b") == "/b" / "a"
  343. when defined(posix):
  344. doAssert absolutePath("a", "/b/") == "/b" / "a"
  345. doAssert absolutePath("a", "/b/c") == "/b/c" / "a"
  346. doAssert absolutePath("/a", "b/") == "/a"
  347. block splitFile:
  348. doAssert splitFile("") == ("", "", "")
  349. doAssert splitFile("abc/") == ("abc", "", "")
  350. doAssert splitFile("/") == ("/", "", "")
  351. doAssert splitFile("./abc") == (".", "abc", "")
  352. doAssert splitFile(".txt") == ("", ".txt", "")
  353. doAssert splitFile("abc/.txt") == ("abc", ".txt", "")
  354. doAssert splitFile("abc") == ("", "abc", "")
  355. doAssert splitFile("abc.txt") == ("", "abc", ".txt")
  356. doAssert splitFile("/abc.txt") == ("/", "abc", ".txt")
  357. doAssert splitFile("/foo/abc.txt") == ("/foo", "abc", ".txt")
  358. doAssert splitFile("/foo/abc.txt.gz") == ("/foo", "abc.txt", ".gz")
  359. doAssert splitFile(".") == ("", ".", "")
  360. doAssert splitFile("abc/.") == ("abc", ".", "")
  361. doAssert splitFile("..") == ("", "..", "")
  362. doAssert splitFile("a/..") == ("a", "..", "")
  363. doAssert splitFile("/foo/abc....txt") == ("/foo", "abc...", ".txt")
  364. # execShellCmd is tested in tosproc
  365. block ospaths:
  366. doAssert unixToNativePath("") == ""
  367. doAssert unixToNativePath(".") == $CurDir
  368. doAssert unixToNativePath("..") == $ParDir
  369. doAssert isAbsolute(unixToNativePath("/"))
  370. doAssert isAbsolute(unixToNativePath("/", "a"))
  371. doAssert isAbsolute(unixToNativePath("/a"))
  372. doAssert isAbsolute(unixToNativePath("/a", "a"))
  373. doAssert isAbsolute(unixToNativePath("/a/b"))
  374. doAssert isAbsolute(unixToNativePath("/a/b", "a"))
  375. doAssert unixToNativePath("a/b") == joinPath("a", "b")
  376. when defined(macos):
  377. doAssert unixToNativePath("./") == ":"
  378. doAssert unixToNativePath("./abc") == ":abc"
  379. doAssert unixToNativePath("../abc") == "::abc"
  380. doAssert unixToNativePath("../../abc") == ":::abc"
  381. doAssert unixToNativePath("/abc", "a") == "abc"
  382. doAssert unixToNativePath("/abc/def", "a") == "abc:def"
  383. elif doslikeFileSystem:
  384. doAssert unixToNativePath("./") == ".\\"
  385. doAssert unixToNativePath("./abc") == ".\\abc"
  386. doAssert unixToNativePath("../abc") == "..\\abc"
  387. doAssert unixToNativePath("../../abc") == "..\\..\\abc"
  388. doAssert unixToNativePath("/abc", "a") == "a:\\abc"
  389. doAssert unixToNativePath("/abc/def", "a") == "a:\\abc\\def"
  390. else:
  391. #Tests for unix
  392. doAssert unixToNativePath("./") == "./"
  393. doAssert unixToNativePath("./abc") == "./abc"
  394. doAssert unixToNativePath("../abc") == "../abc"
  395. doAssert unixToNativePath("../../abc") == "../../abc"
  396. doAssert unixToNativePath("/abc", "a") == "/abc"
  397. doAssert unixToNativePath("/abc/def", "a") == "/abc/def"
  398. block extractFilenameTest:
  399. doAssert extractFilename("") == ""
  400. when defined(posix):
  401. doAssert extractFilename("foo/bar") == "bar"
  402. doAssert extractFilename("foo/bar.txt") == "bar.txt"
  403. doAssert extractFilename("foo/") == ""
  404. doAssert extractFilename("/") == ""
  405. when doslikeFileSystem:
  406. doAssert extractFilename(r"foo\bar") == "bar"
  407. doAssert extractFilename(r"foo\bar.txt") == "bar.txt"
  408. doAssert extractFilename(r"foo\") == ""
  409. doAssert extractFilename(r"C:\") == ""
  410. block lastPathPartTest:
  411. doAssert lastPathPart("") == ""
  412. when defined(posix):
  413. doAssert lastPathPart("foo/bar.txt") == "bar.txt"
  414. doAssert lastPathPart("foo/") == "foo"
  415. doAssert lastPathPart("/") == ""
  416. when doslikeFileSystem:
  417. doAssert lastPathPart(r"foo\bar.txt") == "bar.txt"
  418. doAssert lastPathPart(r"foo\") == "foo"
  419. template canon(x): untyped = normalizePath(x, '/')
  420. doAssert canon"/foo/../bar" == "/bar"
  421. doAssert canon"foo/../bar" == "bar"
  422. doAssert canon"/f/../bar///" == "/bar"
  423. doAssert canon"f/..////bar" == "bar"
  424. doAssert canon"../bar" == "../bar"
  425. doAssert canon"/../bar" == "/../bar"
  426. doAssert canon("foo/../../bar/") == "../bar"
  427. doAssert canon("./bla/blob/") == "bla/blob"
  428. doAssert canon(".hiddenFile") == ".hiddenFile"
  429. doAssert canon("./bla/../../blob/./zoo.nim") == "../blob/zoo.nim"
  430. doAssert canon("C:/file/to/this/long") == "C:/file/to/this/long"
  431. doAssert canon("") == ""
  432. doAssert canon("foobar") == "foobar"
  433. doAssert canon("f/////////") == "f"
  434. doAssert relativePath("/foo/bar//baz.nim", "/foo", '/') == "bar/baz.nim"
  435. doAssert normalizePath("./foo//bar/../baz", '/') == "foo/baz"
  436. doAssert relativePath("/Users/me/bar/z.nim", "/Users/other/bad", '/') == "../../me/bar/z.nim"
  437. doAssert relativePath("/Users/me/bar/z.nim", "/Users/other", '/') == "../me/bar/z.nim"
  438. doAssert relativePath("/Users///me/bar//z.nim", "//Users/", '/') == "me/bar/z.nim"
  439. doAssert relativePath("/Users/me/bar/z.nim", "/Users/me", '/') == "bar/z.nim"
  440. doAssert relativePath("", "/users/moo", '/') == ""
  441. doAssert relativePath("foo", "", '/') == "foo"
  442. doAssert relativePath("/foo", "/Foo", '/') == (when FileSystemCaseSensitive: "../foo" else: ".")
  443. doAssert relativePath("/Foo", "/foo", '/') == (when FileSystemCaseSensitive: "../Foo" else: ".")
  444. doAssert relativePath("/foo", "/fOO", '/') == (when FileSystemCaseSensitive: "../foo" else: ".")
  445. doAssert relativePath("/foO", "/foo", '/') == (when FileSystemCaseSensitive: "../foO" else: ".")
  446. doAssert relativePath("foo", ".", '/') == "foo"
  447. doAssert relativePath(".", ".", '/') == "."
  448. doAssert relativePath("..", ".", '/') == ".."
  449. doAssert relativePath("foo", "foo") == "."
  450. doAssert relativePath("", "foo") == ""
  451. doAssert relativePath("././/foo", "foo//./") == "."
  452. doAssert relativePath(getCurrentDir() / "bar", "foo") == "../bar".unixToNativePath
  453. doAssert relativePath("bar", getCurrentDir() / "foo") == "../bar".unixToNativePath
  454. when doslikeFileSystem:
  455. doAssert relativePath(r"c:\foo.nim", r"C:\") == r"foo.nim"
  456. doAssert relativePath(r"c:\foo\bar\baz.nim", r"c:\foo") == r"bar\baz.nim"
  457. doAssert relativePath(r"c:\foo\bar\baz.nim", r"d:\foo") == r"c:\foo\bar\baz.nim"
  458. doAssert relativePath(r"\foo\baz.nim", r"\foo") == r"baz.nim"
  459. doAssert relativePath(r"\foo\bar\baz.nim", r"\bar") == r"..\foo\bar\baz.nim"
  460. doAssert relativePath(r"\\foo\bar\baz.nim", r"\\foo\bar") == r"baz.nim"
  461. doAssert relativePath(r"\\foo\bar\baz.nim", r"\\foO\bar") == r"baz.nim"
  462. doAssert relativePath(r"\\foo\bar\baz.nim", r"\\bar\bar") == r"\\foo\bar\baz.nim"
  463. doAssert relativePath(r"\\foo\bar\baz.nim", r"\\foo\car") == r"\\foo\bar\baz.nim"
  464. doAssert relativePath(r"\\foo\bar\baz.nim", r"\\goo\bar") == r"\\foo\bar\baz.nim"
  465. doAssert relativePath(r"\\foo\bar\baz.nim", r"c:\") == r"\\foo\bar\baz.nim"
  466. doAssert relativePath(r"\\foo\bar\baz.nim", r"\foo") == r"\\foo\bar\baz.nim"
  467. doAssert relativePath(r"c:\foo.nim", r"\foo") == r"c:\foo.nim"
  468. doAssert joinPath("usr", "") == unixToNativePath"usr"
  469. doAssert joinPath("", "lib") == "lib"
  470. doAssert joinPath("", "/lib") == unixToNativePath"/lib"
  471. doAssert joinPath("usr/", "/lib") == unixToNativePath"usr/lib"
  472. doAssert joinPath("", "") == unixToNativePath"" # issue #13455
  473. doAssert joinPath("", "/") == unixToNativePath"/"
  474. doAssert joinPath("/", "/") == unixToNativePath"/"
  475. doAssert joinPath("/", "") == unixToNativePath"/"
  476. doAssert joinPath("/" / "") == unixToNativePath"/" # weird test case...
  477. doAssert joinPath("/", "/a/b/c") == unixToNativePath"/a/b/c"
  478. doAssert joinPath("foo/", "") == unixToNativePath"foo/"
  479. doAssert joinPath("foo/", "abc") == unixToNativePath"foo/abc"
  480. doAssert joinPath("foo//./", "abc/.//") == unixToNativePath"foo/abc/"
  481. doAssert joinPath("foo", "abc") == unixToNativePath"foo/abc"
  482. doAssert joinPath("", "abc") == unixToNativePath"abc"
  483. doAssert joinPath("zook/.", "abc") == unixToNativePath"zook/abc"
  484. # controversial: inconsistent with `joinPath("zook/.","abc")`
  485. # on linux, `./foo` and `foo` are treated a bit differently for executables
  486. # but not `./foo/bar` and `foo/bar`
  487. doAssert joinPath(".", "/lib") == unixToNativePath"./lib"
  488. doAssert joinPath(".", "abc") == unixToNativePath"./abc"
  489. # cases related to issue #13455
  490. doAssert joinPath("foo", "", "") == "foo"
  491. doAssert joinPath("foo", "") == "foo"
  492. doAssert joinPath("foo/", "") == unixToNativePath"foo/"
  493. doAssert joinPath("foo/", ".") == "foo"
  494. doAssert joinPath("foo", "./") == unixToNativePath"foo/"
  495. doAssert joinPath("foo", "", "bar/") == unixToNativePath"foo/bar/"
  496. # issue #13579
  497. doAssert joinPath("/foo", "../a") == unixToNativePath"/a"
  498. doAssert joinPath("/foo/", "../a") == unixToNativePath"/a"
  499. doAssert joinPath("/foo/.", "../a") == unixToNativePath"/a"
  500. doAssert joinPath("/foo/.b", "../a") == unixToNativePath"/foo/a"
  501. doAssert joinPath("/foo///", "..//a/") == unixToNativePath"/a/"
  502. doAssert joinPath("foo/", "../a") == unixToNativePath"a"
  503. when doslikeFileSystem:
  504. doAssert joinPath("C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\Tools\\", "..\\..\\VC\\vcvarsall.bat") == r"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
  505. doAssert joinPath("C:\\foo", "..\\a") == r"C:\a"
  506. doAssert joinPath("C:\\foo\\", "..\\a") == r"C:\a"
  507. block getTempDir:
  508. block TMPDIR:
  509. # TMPDIR env var is not used if either of these are defined.
  510. when not (defined(tempDir) or defined(windows) or defined(android)):
  511. if existsEnv("TMPDIR"):
  512. let origTmpDir = getEnv("TMPDIR")
  513. putEnv("TMPDIR", "/mytmp")
  514. doAssert getTempDir() == "/mytmp/"
  515. delEnv("TMPDIR")
  516. doAssert getTempDir() == "/tmp/"
  517. putEnv("TMPDIR", origTmpDir)
  518. else:
  519. doAssert getTempDir() == "/tmp/"
  520. block: # getCacheDir
  521. doAssert getCacheDir().dirExists
  522. block isRelativeTo:
  523. doAssert isRelativeTo("/foo", "/")
  524. doAssert isRelativeTo("/foo/bar", "/foo")
  525. doAssert isRelativeTo("foo/bar", "foo")
  526. doAssert isRelativeTo("/foo/bar.nim", "/foo/bar.nim")
  527. doAssert isRelativeTo("./foo/", "foo")
  528. doAssert isRelativeTo("foo", "./foo/")
  529. doAssert isRelativeTo(".", ".")
  530. doAssert isRelativeTo("foo/bar", ".")
  531. doAssert not isRelativeTo("foo/bar.nims", "foo/bar.nim")
  532. doAssert not isRelativeTo("/foo2", "/foo")
  533. block: # quoteShellWindows
  534. doAssert quoteShellWindows("aaa") == "aaa"
  535. doAssert quoteShellWindows("aaa\"") == "aaa\\\""
  536. doAssert quoteShellWindows("") == "\"\""
  537. block: # quoteShellCommand
  538. when defined(windows):
  539. doAssert quoteShellCommand(["a b c", "d", "e"]) == """"a b c" d e"""
  540. doAssert quoteShellCommand(["""ab"c""", r"\", "d"]) == """ab\"c \ d"""
  541. doAssert quoteShellCommand(["""ab"c""", """ \""", "d"]) == """ab\"c " \\" d"""
  542. doAssert quoteShellCommand(["""a\\\b""", """de fg""", "h"]) == """a\\\b "de fg" h"""
  543. doAssert quoteShellCommand(["""a\"b""", "c", "d"]) == """a\\\"b c d"""
  544. doAssert quoteShellCommand(["""a\\b c""", "d", "e"]) == """"a\\b c" d e"""
  545. doAssert quoteShellCommand(["""a\\b\ c""", "d", "e"]) == """"a\\b\ c" d e"""
  546. doAssert quoteShellCommand(["ab", ""]) == """ab """""
  547. block: # quoteShellPosix
  548. doAssert quoteShellPosix("aaa") == "aaa"
  549. doAssert quoteShellPosix("aaa a") == "'aaa a'"
  550. doAssert quoteShellPosix("") == "''"
  551. doAssert quoteShellPosix("a'a") == "'a'\"'\"'a'"
  552. block: # quoteShell
  553. when defined(posix):
  554. doAssert quoteShell("") == "''"
  555. block: # normalizePathEnd
  556. # handle edge cases correctly: shouldn't affect whether path is
  557. # absolute/relative
  558. doAssert "".normalizePathEnd(true) == ""
  559. doAssert "".normalizePathEnd(false) == ""
  560. doAssert "/".normalizePathEnd(true) == $DirSep
  561. doAssert "/".normalizePathEnd(false) == $DirSep
  562. when defined(posix):
  563. doAssert "//".normalizePathEnd(false) == "/"
  564. doAssert "foo.bar//".normalizePathEnd == "foo.bar"
  565. doAssert "bar//".normalizePathEnd(trailingSep = true) == "bar/"
  566. when defined(windows):
  567. doAssert r"C:\foo\\".normalizePathEnd == r"C:\foo"
  568. doAssert r"C:\foo".normalizePathEnd(trailingSep = true) == r"C:\foo\"
  569. # this one is controversial: we could argue for returning `D:\` instead,
  570. # but this is simplest.
  571. doAssert r"D:\".normalizePathEnd == r"D:"
  572. doAssert r"E:/".normalizePathEnd(trailingSep = true) == r"E:\"
  573. doAssert "/".normalizePathEnd == r"\"
  574. block: # isValidFilename
  575. # Negative Tests.
  576. doAssert not isValidFilename("abcd", maxLen = 2)
  577. doAssert not isValidFilename("0123456789", maxLen = 8)
  578. doAssert not isValidFilename("con")
  579. doAssert not isValidFilename("aux")
  580. doAssert not isValidFilename("prn")
  581. doAssert not isValidFilename("OwO|UwU")
  582. doAssert not isValidFilename(" foo")
  583. doAssert not isValidFilename("foo ")
  584. doAssert not isValidFilename("foo.")
  585. doAssert not isValidFilename("con.txt")
  586. doAssert not isValidFilename("aux.bat")
  587. doAssert not isValidFilename("prn.exe")
  588. doAssert not isValidFilename("nim>.nim")
  589. doAssert not isValidFilename(" foo.log")
  590. # Positive Tests.
  591. doAssert isValidFilename("abcd", maxLen = 42.Positive)
  592. doAssert isValidFilename("c0n")
  593. doAssert isValidFilename("foo.aux")
  594. doAssert isValidFilename("bar.prn")
  595. doAssert isValidFilename("OwO_UwU")
  596. doAssert isValidFilename("cron")
  597. doAssert isValidFilename("ux.bat")
  598. doAssert isValidFilename("nim.nim")
  599. doAssert isValidFilename("foo.log")
  600. import sugar
  601. block: # normalizeExe
  602. doAssert "".dup(normalizeExe) == ""
  603. when defined(posix):
  604. doAssert "foo".dup(normalizeExe) == "./foo"
  605. doAssert "foo/../bar".dup(normalizeExe) == "foo/../bar"
  606. when defined(windows):
  607. doAssert "foo".dup(normalizeExe) == "foo"
  608. block: # isAdmin
  609. let isAzure = existsEnv("TF_BUILD") # xxx factor with testament.specs.isAzure
  610. # In Azure on Windows tests run as an admin user
  611. if isAzure and defined(windows): doAssert isAdmin()
  612. # In Azure on POSIX tests run as a normal user
  613. if isAzure and defined(posix): doAssert not isAdmin()