From 0f665666201146069647d1686e2ff565d469097b Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 13 Jul 2011 17:36:59 -0400
Subject: Introduce support for C++ integration tests running Python scripts.
 This is in its infancy; tested on Mac; needs to be ironed out on Windows and
 Linux. Goal is to test at least some cross-language LLSD serialization.

---
 indra/llcommon/CMakeLists.txt               |  3 +-
 indra/llcommon/tests/llsdserialize_test.cpp | 97 ++++++++++++++++++++++++-----
 indra/llcommon/tests/setpython.py           | 19 ++++++
 3 files changed, 103 insertions(+), 16 deletions(-)
 create mode 100644 indra/llcommon/tests/setpython.py

(limited to 'indra')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 9910281b64..c755020a64 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -317,7 +317,8 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llprocessor "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
-  LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}"
+                          "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/setpython.py")
   LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}")
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index 7b4c7d6a48..75b79467b7 100644
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -25,33 +25,26 @@
  * $/LicenseInfo$
  */
 
-#if !LL_WINDOWS
-#include <netinet/in.h>
-#endif
-
 #include "linden_common.h"
 #include "../llsd.h"
 #include "../llsdserialize.h"
 #include "../llformat.h"
 
 #include "../test/lltut.h"
-
+#include "llprocesslauncher.h"
+#include "stringize.h"
 
 #if LL_WINDOWS
 #include <winsock2.h>
 typedef U32 uint32_t;
+#else
+#include <netinet/in.h>
+#include <errno.h>
 #endif
 
-std::vector<U8> string_to_vector(std::string str)
+std::vector<U8> string_to_vector(const std::string& str)
 {
-	// bc LLSD can't...
-	size_t len = (size_t)str.length();
-	std::vector<U8> v(len);
-	for (size_t i = 0; i < len ; i++)
-	{
-		v[i] = str[i];
-	}
-	return v;
+	return std::vector<U8>(str.begin(), str.end());
 }
 
 namespace tut
@@ -1494,5 +1487,79 @@ namespace tut
 		ensureBinaryAndNotation("map", test);
 		ensureBinaryAndXML("map", test);
 	}
-}
 
+    struct TestPythonCompatible
+    {
+        TestPythonCompatible() {}
+        ~TestPythonCompatible() {}
+
+        void python(const std::string& desc, const std::string& script, F32 timeout=5)
+        {
+            const char* PYTHON(getenv("PYTHON"));
+            ensure("Set $PYTHON to the Python interpreter", PYTHON);
+            LLProcessLauncher py;
+            py.setExecutable(PYTHON);
+            py.addArgument("-c");
+            py.addArgument(script);
+            ensure_equals(STRINGIZE("Couldn't launch " << desc << " script"), py.launch(), 0);
+
+#if LL_WINDOWS
+            ensure_equals(STRINGIZE(desc << " script ran beyond "
+                                    << std::fixed << std::setprecision(1)
+                                    << timeout << " seconds"),
+                          WaitForSingleObject(py.getProcessHandle(), DWORD(timeout * 1000)),
+                          WAIT_OBJECT_0);
+            DWORD rc(0);
+            GetExitCodeProcess(py.getProcessHandle(), &rc);
+            ensure_equals(STRINGIZE(desc << " script terminated with rc " << rc), rc, 0);
+#else
+            // Implementing timeout would mean messing with alarm() and
+            // catching SIGALRM... later maybe...
+            int status(0);
+            if (waitpid(py.getProcessID(), &status, 0) == -1)
+            {
+                int waitpid_errno(errno);
+                ensure_equals(STRINGIZE("Couldn't retrieve rc from " << desc << " script: "
+                                        "waitpid() errno " << waitpid_errno),
+                              waitpid_errno, ECHILD);
+            }
+            else
+            {
+                if (WIFEXITED(status))
+                {
+                    int rc(WEXITSTATUS(status));
+                    ensure_equals(STRINGIZE(desc << " script terminated with rc " << rc), rc, 0);
+                }
+                else if (WIFSIGNALED(status))
+                {
+                    ensure(STRINGIZE(desc << " script terminated by signal " << WTERMSIG(status)),
+                           false);
+                }
+                else
+                {
+                    ensure(STRINGIZE(desc << " script produced impossible status " << status),
+                           false);
+                }
+            }
+#endif
+        }
+    };
+
+    typedef tut::test_group<TestPythonCompatible> TestPythonCompatibleGroup;
+    typedef TestPythonCompatibleGroup::object TestPythonCompatibleObject;
+    TestPythonCompatibleGroup pycompat("LLSD serialize Python compatibility");
+
+    template<> template<>
+    void TestPythonCompatibleObject::test<1>()
+    {
+        python("hello", "print 'Hello, world!'");
+    }
+
+    template<> template<>
+    void TestPythonCompatibleObject::test<2>()
+    {
+        python("platform",
+"import sys\n"
+"print 'Running on', sys.platform");
+    }
+}
diff --git a/indra/llcommon/tests/setpython.py b/indra/llcommon/tests/setpython.py
new file mode 100644
index 0000000000..df7b90428e
--- /dev/null
+++ b/indra/llcommon/tests/setpython.py
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+"""\
+@file   setpython.py
+@author Nat Goodspeed
+@date   2011-07-13
+@brief  Set PYTHON environment variable for tests that care.
+
+$LicenseInfo:firstyear=2011&license=viewerlgpl$
+Copyright (c) 2011, Linden Research, Inc.
+$/LicenseInfo$
+"""
+
+import os
+import sys
+import subprocess
+
+if __name__ == "__main__":
+    os.environ["PYTHON"] = sys.executable
+    sys.exit(subprocess.call(sys.argv[1:]))
-- 
cgit v1.2.3