[Lldb-commits] [lldb] r257669 - Fix TestProcessLaunch for Python 3.

Zachary Turner via lldb-commits lldb-commits at lists.llvm.org
Wed Jan 13 13:21:50 PST 2016


Author: zturner
Date: Wed Jan 13 15:21:49 2016
New Revision: 257669

URL: http://llvm.org/viewvc/llvm-project?rev=257669&view=rev
Log:
Fix TestProcessLaunch for Python 3.

There were a number of problems preventing this from working:

1. The SWIG typemaps for converting Python lists to and from C++
   arrays were not updated for Python 3.  So they were doing things
   like PyString_Check instead of using the PythonString from
   PythonDataObjects.
2. ProcessLauncherWindows was ignoring the environment completely.
   So any test that involved launching an inferior with any kind
   of environment variable would have failed.
3. The test itself was using process.GetSTDOUT(), which isn't
   implemented on Windows.  So this was changed to save the
   value of the environment variable in a local variable and
   have the debugger look at the value of the variable.

Modified:
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_launch/TestProcessLaunch.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_launch/print_env.cpp
    lldb/trunk/scripts/Python/python-typemaps.swig
    lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_launch/TestProcessLaunch.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_launch/TestProcessLaunch.py?rev=257669&r1=257668&r2=257669&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_launch/TestProcessLaunch.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_launch/TestProcessLaunch.py Wed Jan 13 15:21:49 2016
@@ -4,12 +4,15 @@ Test lldb process launch flags.
 
 from __future__ import print_function
 
+import copy
+import os
+import time
 
-
-import os, time
 import lldb
 from lldbsuite.test.lldbtest import *
 
+import six
+
 class ProcessLaunchTestCase(TestBase):
 
     mydir = TestBase.compute_mydir(__file__)
@@ -17,9 +20,18 @@ class ProcessLaunchTestCase(TestBase):
     def setUp(self):
         # Call super's setUp().
         TestBase.setUp(self)
+        self.stdout_redirect_file = 'lldb-stdout-redirect.txt'
         # disable "There is a running process, kill it and restart?" prompt
         self.runCmd("settings set auto-confirm true")
-        self.addTearDownHook(lambda: self.runCmd("settings clear auto-confirm"))
+    def tearDown(self):
+        self.runCmd("settings clear auto-confirm")
+
+        try:
+            os.unlink(self.stdout_redirect_file)
+        except:
+            pass
+
+        super().tearDown()
 
     @not_remote_testsuite_ready
     def test_io (self):
@@ -180,8 +192,9 @@ class ProcessLaunchTestCase(TestBase):
             self.fail(err_msg)
 
     def test_environment_with_special_char (self):
-        """Test that environment variables containing '*' and '}' are communicated correctly to the lldb-server."""
-        d = {'CXX_SOURCES' : 'print_env.cpp'}
+        """Test that environment variables containing '*' and '}' are handled correctly by the inferior."""
+        source = 'print_env.cpp'
+        d = {'CXX_SOURCES' : source}
         self.build(dictionary=d)
         self.setTearDownCleanup(d)
         exe = os.path.join (os.getcwd(), "a.out")
@@ -189,19 +202,19 @@ class ProcessLaunchTestCase(TestBase):
         evil_var = 'INIT*MIDDLE}TAIL'
 
         target = self.dbg.CreateTarget(exe)
+        main_source_spec = lldb.SBFileSpec(source)
+        breakpoint = target.BreakpointCreateBySourceRegex('// Set breakpoint here.', main_source_spec)
+
         process = target.LaunchSimple(None, ['EVIL=' + evil_var], self.get_process_working_directory())
-        self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED)
+        self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
 
-        out = process.GetSTDOUT(len(evil_var))
-        self.assertIsNotNone(out, "Encountered an error reading the process's output")
+        threads = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint)
+        self.assertEqual(len(threads), 1)
+        frame = threads[0].GetFrameAtIndex(0)
+        sbvalue = frame.EvaluateExpression("evil")
+        value = sbvalue.GetSummary().strip('"')
 
-        out = out[:len(evil_var)]
-        if out != evil_var:
-            self.fail('The environment variable was mis-coded: %s\n' % repr(out))
-
-        newline = process.GetSTDOUT(1)
-        self.assertIsNotNone(newline, "Encountered an error reading the process's output")
-
-        newline = newline[0]
-        if newline != '\r' and newline != '\n':
-            self.fail('Garbage at end of environment variable')
+        self.assertEqual(value, evil_var)
+        process.Continue()
+        self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED)
+        pass
\ No newline at end of file

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_launch/print_env.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_launch/print_env.cpp?rev=257669&r1=257668&r2=257669&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_launch/print_env.cpp (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_launch/print_env.cpp Wed Jan 13 15:21:49 2016
@@ -5,7 +5,6 @@
 int main (int argc, char **argv)
 {
   char *evil = getenv("EVIL");
-  puts(evil);
 
-  return 0;
+  return 0;  // Set breakpoint here.
 }

Modified: lldb/trunk/scripts/Python/python-typemaps.swig
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/python-typemaps.swig?rev=257669&r1=257668&r2=257669&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/python-typemaps.swig (original)
+++ lldb/trunk/scripts/Python/python-typemaps.swig Wed Jan 13 15:21:49 2016
@@ -1,20 +1,22 @@
 /* Typemap definitions, to allow SWIG to properly handle 'char**' data types. */
 
 %typemap(in) char ** {
+  using namespace lldb_private;
   /* Check if is a list  */
-  if (PyList_Check($input)) {
-    int size = PyList_Size($input);
+  if (PythonList::Check($input)) {
+    PythonList list(PyRefType::Borrowed, $input);
+    int size = list.GetSize();
     int i = 0;
-    $1 = (char **) malloc((size+1) * sizeof(char*));
+    $1 = (char**)malloc((size+1)*sizeof(char*));
     for (i = 0; i < size; i++) {
-      PyObject *o = PyList_GetItem($input,i);
-      if (PyString_Check(o))
-        $1[i] = PyString_AsString(o);
-      else {
+      PythonString py_str = list.GetItemAtIndex(i).AsType<PythonString>();
+      if (!py_str.IsAllocated()) {
         PyErr_SetString(PyExc_TypeError,"list must contain strings");
         free($1);
-        return NULL;
+        return nullptr;
       }
+
+      $1[i] = const_cast<char*>(py_str.GetString().data());
     }
     $1[i] = 0;
   } else if ($input == Py_None) {
@@ -42,12 +44,14 @@
 %typemap(typecheck) char ** {
   /* Check if is a list  */
   $1 = 1;
-  if (PyList_Check($input)) {
-    int size = PyList_Size($input);
+  using namespace lldb_private;
+  if (PythonList::Check($input)) {
+    PythonList list(PyRefType::Borrowed, $input);
+    int size = list.GetSize();
     int i = 0;
     for (i = 0; i < size; i++) {
-      PyObject *o = PyList_GetItem($input,i);
-      if (!PyString_Check(o)) { $1 = 0; }
+      PythonString s = list.GetItemAtIndex(i).AsType<PythonString>();
+      if (!s.IsAllocated()) { $1 = 0; }
     }
   }
   else
@@ -81,13 +85,12 @@
 
     $1 = (char**)malloc((size+1)*sizeof(char*));
     for (int i = 0; i < size; i++) {
-      PythonObject o = py_list.GetItemAtIndex(i);
-      if (!PythonString::Check(o.get())) {
+      auto py_str = py_list.GetItemAtIndex(i).AsType<PythonString>();
+      if (!py_str.IsAllocated()) {
         PyErr_SetString(PyExc_TypeError,"list must contain strings");
         free($1);
         return nullptr;
       }
-      auto py_str = o.AsType<PythonString>();
       $1[i] = const_cast<char*>(py_str.GetString().data());
     }
 
@@ -101,14 +104,16 @@
 }
 
 %typemap(typecheck) char const ** {
+  using namespace lldb_private;
   /* Check if is a list  */
   $1 = 1;
-  if (PyList_Check($input)) {
-    int size = PyList_Size($input);
+  if (PythonList::Check($input)) {
+    PythonList list(PyRefType::Borrowed, $input);
+    int size = list.GetSize();
     int i = 0;
     for (i = 0; i < size; i++) {
-      PyObject *o = PyList_GetItem($input,i);
-      if (!PyString_Check(o)) { $1 = 0; }
+      PythonString s = list.GetItemAtIndex(i).AsType<PythonString>();
+      if (!s.IsAllocated()) { $1 = 0; }
     }
   }
   else
@@ -126,10 +131,13 @@
   int i;
   len = 0;
   while ($1[len]) len++;
-  $result = PyList_New(len);
+  using namespace lldb_private;
+  PythonList list(len);
   for (i = 0; i < len; i++) {
-    PyList_SetItem($result, i, PyString_FromString($1[i]));
+    PythonString str($1[i]);
+    list.SetItemAtIndex(i, str);
   }
+  $result = list.release();
 }
 
 /* Typemap definitions to allow SWIG to properly handle char buffer. */

Modified: lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp?rev=257669&r1=257668&r2=257669&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp (original)
+++ lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp Wed Jan 13 15:21:49 2016
@@ -17,6 +17,31 @@
 using namespace lldb;
 using namespace lldb_private;
 
+namespace
+{
+void
+CreateEnvironmentBuffer(const Args &env, std::vector<char> &buffer)
+{
+    if (env.GetArgumentCount() == 0)
+        return;
+
+    int bytes = 0;
+    for (int i = 0; i < env.GetArgumentCount(); ++i)
+        bytes += strlen(env.GetArgumentAtIndex(i)) + sizeof(char);
+    bytes += sizeof(char);
+    buffer.resize(bytes);
+    char *cur_entry = &buffer[0];
+    for (int i = 0; i < env.GetArgumentCount(); ++i)
+    {
+        ::strcpy(cur_entry, env.GetArgumentAtIndex(i));
+        cur_entry += strlen(cur_entry) + sizeof(char);
+    }
+    // Environment buffer is a null terminated list of null terminated
+    // strings, so it is terminated by two null bytes.
+    buffer.back() = 0;
+}
+}
+
 HostProcess
 ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error)
 {
@@ -49,10 +74,16 @@ ProcessLauncherWindows::LaunchProcess(co
     if (launch_info.GetFlags().Test(eLaunchFlagDebug))
         flags |= DEBUG_ONLY_THIS_PROCESS;
 
+    auto &env = const_cast<Args &>(launch_info.GetEnvironmentEntries());
+    LPVOID env_block = nullptr;
+    ::CreateEnvironmentBuffer(env, environment);
+    if (!environment.empty())
+        env_block = environment.data();
+
     executable = launch_info.GetExecutableFile().GetPath();
     launch_info.GetArguments().GetQuotedCommandString(commandLine);
-    BOOL result = ::CreateProcessA(executable.c_str(), const_cast<char *>(commandLine.c_str()), NULL, NULL, TRUE, flags, NULL,
-                                   launch_info.GetWorkingDirectory().GetCString(), &startupinfo, &pi);
+    BOOL result = ::CreateProcessA(executable.c_str(), const_cast<char *>(commandLine.c_str()), NULL, NULL, TRUE, flags,
+                                   env_block, launch_info.GetWorkingDirectory().GetCString(), &startupinfo, &pi);
     if (result)
     {
         // Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess.




More information about the lldb-commits mailing list