[Lldb-commits] [PATCH] D17492: Case sensitive path compare on Windows breaks breakpoints
Zachary Turner via lldb-commits
lldb-commits at lists.llvm.org
Mon Feb 22 11:16:10 PST 2016
zturner added a comment.
This probably seems like a lot of comments, but most of them are pretty minor. Overall this looks like a good patch. When running the test suite with this patch, did any tests start showing up as Unexpected Success?
================
Comment at: packages/Python/lldbsuite/test/dotest.py:288-294
@@ -288,1 +287,9 @@
+
+ if sys.platform.startswith('win32'):
+ import ctypes, time
+ while not ctypes.windll.kernel32.IsDebuggerPresent():
+ time.sleep(0.5)
+ ctypes.windll.kernel32.DebugBreak()
+ else:
+ os.kill(os.getpid(), signal.SIGSTOP)
----------------
See if you can get [[ https://github.com/Microsoft/PTVS/releases | PTVS ]] to work. If so, you won't need any of this code and it will be a much better debugging experience anyway. Assuming PTVS works for you, I'd rather just delete this code. I'm planning to add info about using PTVS to the website this week.
================
Comment at: packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/TestBreakpointCaseSensitivity.py:20
@@ +19,3 @@
+
+ def test_case_sensitivity_breakpoint(self):
+ """Set breakpoint on file, should match files with different case on Windows"""
----------------
When we run the test suite, it's going to report this test as `test_case_sensitivity_breakpoint`. So looking at it, you will have to think for a minute about whether the test was expecting it to match or to not match. It would be nice if the test was called something like `test_breakpoint_matches_file_with_different_case`. So then you would need 2 test methods. One for matching with different case, and one for not matching with different case. Then you could use a decorator to enable them on windows or on not windows. Like this:
```
@skipIf(oslist=no_match(['windows'])) # Skip for non-windows platforms
def test_breakpoint_matches_file_with_different_case(self):
self.build()
self.case_sensitivity_breakpoint(true)
@skipIf(oslist=['windows']) # Skip for windows platforms
def test_breakpoint_doesnt_match_file_with_different_case(self):
self.build()
self.case_sensitivity_breakpoint(false)
```
================
Comment at: packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/TestBreakpointCaseSensitivity.py:25-35
@@ +24,13 @@
+
+ def case_sensitivity_breakpoint(self):
+ """Set breakpoint on file, should match files with different case on Windows"""
+
+ # if breakpoint should hit when file path is case modified
+ should_hit_modified_case = lldbplatformutil.getHostPlatform() == "windows"
+
+ # use different case on Windows
+ if should_hit_modified_case:
+ exe = os.path.join(os.getcwd(), "A.OUT")
+ else:
+ exe = os.path.join(os.getcwd(), "a.out")
+
----------------
Then this whole thing becomes:
```
def case_sensitivity_breakpoint(self, case_insensitive):
exe = "a.out"
if case_insensitive:
exe = strupper(exe)
exe = os.path.join(os.getcwd(), exe)
```
================
Comment at: packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/TestBreakpointCaseSensitivity.py:92-95
@@ +91,6 @@
+
+ # not needed to spawn the process when break is not set
+ if not should_hit:
+ self.target.BreakpointDelete(breakpoint.GetID())
+ return
+
----------------
If `should_hit` is false, then I think we should launch the process anyway, but verify that it DOES NOT get hit. It would look something like this (not tested, maybe some errors here):
```
process = self.target.LaunchSimple(None, None, self.get_process_working_directory())
self.assertTrue(process, PROCESS_IS_VALID + desc)
if should_hit:
# Did we hit our breakpoint?
from lldbsuite.test.lldbutil import get_threads_stopped_at_breakpoint
threads = get_threads_stopped_at_breakpoint (process, breakpoint)
self.assertEqual(1, len(threads), "There should be a thread stopped at breakpoint" + desc)
# The hit count for the breakpoint should be 1.
self.assertEqual(1, breakpoint.GetHitCount())
else:
self.assertEqual(lldb.eStateExited, process.GetState())
================
Comment at: packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/TestBreakpointCaseSensitivity.py:103
@@ +102,3 @@
+ threads = get_threads_stopped_at_breakpoint (process, breakpoint)
+ self.assertTrue(len(threads) == 1, "There should be a thread stopped at breakpoint" + desc)
+ # The hit count for the breakpoint should be 1.
----------------
Minor nitpick, but can you use `assertEqual` here? Same goes for following test. This will provide a better error message, since as the code is written here it will just say "Expected True, got False", but with `assertEqual`, it will say "expected 1, got 0" or something like that.
================
Comment at: packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/TestBreakpointCaseSensitivity.py:108
@@ +107,3 @@
+ # clean after ourself
+ process.Kill()
+ self.target.BreakpointDelete(breakpoint.GetID())
----------------
`process.Kill()` is kind of harsh. I know some tests do it, but usually we just do `process.Continue()` to let it exit gracefully. (It shouldn't matter in practice, so whatever you prefer)
================
Comment at: packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/TestBreakpointCaseSensitivity.py:109
@@ +108,2 @@
+ process.Kill()
+ self.target.BreakpointDelete(breakpoint.GetID())
----------------
This line is harmless, but not necessary. Because the test runner should end up deleting the target later anyway.
================
Comment at: packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/TestBreakpointCaseSensitivity.py:110
@@ +109,1 @@
+ self.target.BreakpointDelete(breakpoint.GetID())
\ No newline at end of file
----------------
Need newline at end of file.
================
Comment at: packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/main.c:6
@@ +5,3 @@
+{
+ printf ("Set a breakpoint here.\n");
+ return 0;
----------------
Doesn't look like this is clang-formatted. We don't use a space between function name and open parentheses. You'll see a lot of code that does this, but after that code was written we agreed to remove the parentheses. clang-format should remove it for you automatically.
================
Comment at: source/Core/ConstString.cpp:269
@@ +268,3 @@
+bool
+ConstString::Equals (const ConstString& lhs, const ConstString& rhs, const bool case_sensitive)
+{
----------------
Looks like this code also isn't clang-formatted. If you build clang-format (with `ninja clang-format`) and add its folder to your `PATH` environment variable, then when your changes are staged in git, just run `git clang-format`.
If you've already committed you can uncommit with `git reset --soft HEAD`. Then they will be staged again, then you can run `git clang-format`, then re-add all the modified files, and then recommit.
================
Comment at: source/Core/ConstString.cpp:274-275
@@ +273,4 @@
+
+ if (case_sensitive)
+ return false;
+
----------------
I thought this was wrong at first, but then I realized it's right. Can you add a comment above this line:
```
// Since the pointers weren't equal, and identical ConstStrings always have identical pointers, the result must be false.
```
================
Comment at: source/Host/common/FileSpec.cpp:400
@@ +399,3 @@
+ // case sensitivity of file check
+ const bool case_sensitive = m_syntax != ePathSyntaxWindows;
+
----------------
There is a minor edge case that isn't handled here, when `*this` and `rhs` have different syntaxes. Granted if that's ever the case, it's very unlikely that the `FileSpecs` would be otherwise the same, but it's possible (especially if `m_directory` is not set).
So I think we should add a method to `FileSpec`
```
bool IsCaseSensitive() const { return m_syntax != ePathSyntaxWindows; }
```
Then this line becomes:
```
const bool case_sensitive = IsCaseSensitive() || rhs.IsCaseSensitive();
```
Here the comparison should be case sensitive if *either* `FileSpec` requires a case sensitive comparison, not just `*this`.
================
Comment at: source/Host/common/FileSpec.cpp:402
@@ -400,1 +401,3 @@
+
+ if (ConstString::Equals(m_filename, rhs.m_filename, case_sensitive))
{
----------------
Can you reverse this conditional and just early out if they don't match (I know that wasn't your code, but seems to fit more with LLVM style.
================
Comment at: source/Host/common/FileSpec.cpp:522
@@ -518,3 +521,3 @@
{
- result = ConstString::Compare(a.m_directory, b.m_directory);
+ result = ConstString::Compare(a.m_directory, b.m_directory, a.m_syntax != ePathSyntaxWindows);
if (result)
----------------
If you add the `IsCaseSensitive()` method, then this would change here too (and also you should check `a` and `b` just like I mentioned in the last comment.
Same goes for the rest of the places.
http://reviews.llvm.org/D17492
More information about the lldb-commits
mailing list