diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -767,10 +767,11 @@ std::string path = outfile_spec.GetPath(); if (outfile_spec) { - auto open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; + File::OpenOptions open_options = + File::eOpenOptionWrite | File::eOpenOptionCanCreate; const bool append = m_outfile_options.GetAppend().GetCurrentValue(); - if (append) - open_options |= File::eOpenOptionAppend; + open_options |= + append ? File::eOpenOptionAppend : File::eOpenOptionTruncate; auto outfile = FileSystem::Instance().Open(outfile_spec, open_options); diff --git a/lldb/test/API/functionalities/memory/read/TestMemoryRead.py b/lldb/test/API/functionalities/memory/read/TestMemoryRead.py --- a/lldb/test/API/functionalities/memory/read/TestMemoryRead.py +++ b/lldb/test/API/functionalities/memory/read/TestMemoryRead.py @@ -2,12 +2,12 @@ Test the 'memory read' command. """ - - import lldb -from lldbsuite.test.lldbtest import * import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + class MemoryReadTestCase(TestBase): @@ -19,27 +19,34 @@ # Find the line number to break inside main(). self.line = line_number('main.cpp', '// Set break point at this line.') - def test_memory_read(self): - """Test the 'memory read' command with plain and vector formats.""" + def build_run_stop(self): self.build() exe = self.getBuildArtifact("a.out") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) # Break in main() after the variables are assigned values. - lldbutil.run_break_set_by_file_and_line( - self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + lldbutil.run_break_set_by_file_and_line(self, + "main.cpp", + self.line, + num_expected_locations=1, + loc_exact=True) self.runCmd("run", RUN_SUCCEEDED) # The stop reason of the thread should be breakpoint. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + self.expect("thread list", + STOPPED_DUE_TO_BREAKPOINT, substrs=['stopped', 'stop reason = breakpoint']) # The breakpoint should have a hit count of 1. - self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + self.expect("breakpoint list -f", + BREAKPOINT_HIT_ONCE, substrs=[' resolved, hit count = 1']) - # Test the memory read commands. + @no_debug_info_test + def test_memory_read(self): + """Test the 'memory read' command with plain and vector formats.""" + self.build_run_stop() # (lldb) memory read -f d -c 1 `&argc` # 0x7fff5fbff9a0: 1 @@ -131,3 +138,40 @@ for o in objects_read: self.assertEqual(len(o), expected_object_length) self.assertEquals(len(objects_read), 4) + + @no_debug_info_test + def test_memory_read_file(self): + self.build_run_stop() + res = lldb.SBCommandReturnObject() + self.ci.HandleCommand("memory read -f d -c 1 `&argc`", res) + self.assertTrue(res.Succeeded(), "memory read failed:" + res.GetError()) + + # Record golden output. + golden_output = res.GetOutput() + + memory_read_file = self.getBuildArtifact("memory-read-output") + + def check_file_content(expected): + with open(memory_read_file) as f: + lines = f.readlines() + lines = [s.strip() for s in lines] + expected = [s.strip() for s in expected] + self.assertEqual(lines, expected) + + # Sanity check. + self.runCmd("memory read -f d -c 1 -o '{}' `&argc`".format(memory_read_file)) + check_file_content([golden_output]) + + # Write some garbage to the file. + with open(memory_read_file, 'w') as f: + f.write("some garbage") + + # Make sure the file is truncated when we run the command again. + self.runCmd("memory read -f d -c 1 -o '{}' `&argc`".format(memory_read_file)) + check_file_content([golden_output]) + + # Make sure the file is appended when we run the command with --append-outfile. + self.runCmd( + "memory read -f d -c 1 -o '{}' --append-outfile `&argc`".format( + memory_read_file)) + check_file_content([golden_output, golden_output])