Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[superseded] [os] fix #8734, #8353: parentDir, parentDirs now work reliably #10545

Closed
wants to merge 12 commits into from

Conversation

timotheecour
Copy link
Member

@timotheecour timotheecour commented Feb 4, 2019

parentDir, parentDirs now work reliably

XXX os's parentDirs is stupid (multiple yields) and triggers an old bug...

  • many other issues I saw while working on the fix.

I also added extensive unittests so you can now see exactly what parentDir and parentDirs return

to view the diff and not get confused by code that was only moved, see instructions here https://github.com/nim-lang/Nim/pull/10435/files

note

the # todo: fix is a (commented out) test case for a pre-existing failure from #8395 which i can fix after this PR

Copy link
Member

@Araq Araq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#8734 is arguably not a bug. Especially not if you keep the behaviour that an empty string signals a wrong usage.

lib/pure/os.nim Outdated Show resolved Hide resolved
compiler/packagehandling.nim Outdated Show resolved Hide resolved
tests/stdlib/tos.nim Show resolved Hide resolved
@timotheecour
Copy link
Member Author

#8734 is arguably not a bug. Especially not if you keep the behaviour that an empty string signals a wrong usage.

#8734 is not 1 bug but multiple bugs and as discussed here https://irclogs.nim-lang.org/04-02-2019.html#10:56:02 and elsewhere in this conversation thread some of the items are indeed bugs, and 1 of them is being debated.
So i added a simple CT switch (that is currently set to parentDirOfRootIsEmpty = true ) to unblock this PR and we can address that point later, which'll only require resetting parentDirOfRootIsEmpty = false if we decide to go with that

@timotheecour
Copy link
Member Author

@Araq PTAL all comments addressed

("/a.txt", "/"),
]

doAssert runTestCases("parentDir", examples, parentDir(it))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is cargo-cult programming. Now I can look at a list of tuples all day long before I can see it's about parentDir. DRY and meta programming are for creating higher abstractions, not to save keystrokes.

Copy link
Member Author

@timotheecour timotheecour Feb 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I can look at a list of tuples all day long before I can see it's about parentDir

I just pushed a commit that adds documentation to make everything clear.

I had initially started with the one doAssert per test case but that became quickly un-manageable with the number of test cases, in particular:

  • the important part of each test case was lost in noise of the repetitive surrounding code, eg doAssert parentDir("/usr/local/bin".unixToNativePath) == "/usr/local".unixToNativePath ; instead, I'm only highlighting the part that changes
  • on failure, it doesn't tell you what parentDir produced as output (because you don't like assertEquals for some reason)
  • it stops on 1st error instead of showing all errors, making it terrible when you need to change the implementation of parentDirs; instead I'm showing all errors before failing
  • if you have to change something, you have to change it everywhere; unlike here where I need to change it in only one place. yes, it's DRY, it's not cargo cult

note:

the lack of this kind of thorough testing as done here for parentDir is the root cause for all those issues and regressions I keep running into when using std/os procs (eg #10018 , #10047 , etc)

I have other PR's in the pipeline that fix other bugs in std/os (eg "/a" /../ "d" should be "/d", not "d" + other bugs with other procs) so let's please move on with this PR

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the lack of this kind of thorough testing as done here for parentDir is the root cause for all those issues and regressions I keep running into when using std/os procs (eg #10018 , #10047 , etc)

Maybe but it's just you. Most people don't use double slashes in all their paths. And your improved implementation adds plenty of its own, new problems.

Copy link
Member Author

@timotheecour timotheecour Feb 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Araq

export buildDir=/path/to/build/
export logFile=$buildDir/log.txt # => expands to a path with double slash (`${buildDir}log.txt` in contrast only works if `buildDir` ends with a slash)

To be on the safe side, include the slash. This can lead to multiple slashes when concatenating the paths, but at least you avoid problems.

and this: https://unix.stackexchange.com/questions/1910/how-does-linux-handle-multiple-consecutive-path-separators-home-username

Multiple slashes are allowed and are equivalent to a single slash

And your improved implementation adds plenty of its own, new problems

I'm not sure which are these new problems you're referring to, after this PR was updated to return "" instead of / for parentDir("/"), more precisely: what previously valid code would become incorrect as a result of this PR.

In any case, as mentioned below, I'm following up with #10633

tests/stdlib/tos.nim Outdated Show resolved Hide resolved
@@ -26,6 +26,31 @@ Raises
# test os path creation, iteration, and deletion

import os, strutils, pathnorm
import "$nim/compiler/unittest_light"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unittest is bad because it's full of when compiles. Guess what, unittest_light repeats the mistake. The tests were fine before without this import.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed that import for the sake of moving fwd with this PR, but please explain what is wrong with unittest_light having compiles ?

  • assertEquals is written as if lhs!=rhs: doAssert false, mismatch(lhs, rhs) so the compiles is just used for printing the error msg (inside mismatch), not for correctness validation
  • theres is already a test for that tests/compiler/tunittest_light.nim which tests assertEquals using doAssert so if assertEquals had bugs, doAssert would catch it

If it's a compilation speed issue, there are easy options.

More generally, for assertEquals, unittest.check, fmt, and sequtils: 1 argument I heard against more widespread use in testament was "who is guarding the guardian" argument; I'm all for adding more thorough testing (as needed) for these but we shouldn't use FUD arguments that they may have bugs that would render testament useless;
If a bug ever slips through existing checks, it'll eventually be found in the wild, reported, and fixed;
note, outside of testament, these are pretty popular tools for testing in nimble packages, for a reason.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nim-regex doesn't compile with devel because it uses unittest and unittest does nasty stuff. Yeah, these are compiler regressions, but still, a testing infrastructure shouldn't stress the compiler so much that it becomes hard to debug itself. No FUD here, just lots of experience with unittest.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the concerns you're raising seem specific to unittest, not unittest_light, as I described here #10545 (comment)

lib/pure/os.nim Outdated Show resolved Hide resolved
lib/pure/os.nim Outdated Show resolved Hide resolved
@timotheecour
Copy link
Member Author

@Araq comments addressed and green, PTAL

assert parentDir("/") == ""
if path == "": return ""
result = path
while true:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Convoluted. What's wrong with fixing parentDirPos?

result = path
while true:
normalizePathEnd(result)
let (dir, name, ext) = splitFile(result)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would I do that? What has ext to do with anything?

while true:
normalizePathEnd(result)
let (dir, name, ext) = splitFile(result)
if name == ".." or (name.len == 0 and ext.len == 0): return ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parentDir("bar/baz/foo/..") could just work...

normalizePathEnd(result)
let (dir, name, ext) = splitFile(result)
if name == ".." or (name.len == 0 and ext.len == 0): return ""
if name == ".":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah so silly single dots are allowed.

result = dir
continue
if dir == "" and name != "":
return "."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really? What is this "." directory and if it is one why is ".." not a directory?

continue
if dir == "" and name != "":
return "."
return dir
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point in the control flow it's not obvious if it shouldn't have been return result.

@krux02
Copy link
Contributor

krux02 commented Feb 7, 2019

too long didn't read.

@timotheecour
Copy link
Member Author

timotheecour commented Feb 11, 2019

instead of addressing remaining comments in this PR I'm opening #10633 which has a different, simpler implementation (some edge cases are treated differently) and should address the remaining comments from here; if #10633 gets merged I'll close this PR but preferably not before because github doesn't allow re-opening a closed PR after a force push.

@timotheecour timotheecour changed the title [os] fix #8734, #8353: parentDir, parentDirs now work reliably [superseded] [os] fix #8734, #8353: parentDir, parentDirs now work reliably Feb 11, 2019
@krux02
Copy link
Contributor

krux02 commented Feb 11, 2019

this I am closing this in favor of #10633

@krux02 krux02 closed this Feb 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
OS (stdlib) Related to OS modules in standard library
Projects
None yet
3 participants