[libcxx-commits] [libcxx] 96e48e9 - [libc++] Add the ability to run arbitrary programs using the DSL
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Jun 15 12:00:06 PDT 2020
Author: Louis Dionne
Date: 2020-06-15T14:59:53-04:00
New Revision: 96e48e9a61ad4b5992457169685c5c69e20889b5
URL: https://github.com/llvm/llvm-project/commit/96e48e9a61ad4b5992457169685c5c69e20889b5
DIFF: https://github.com/llvm/llvm-project/commit/96e48e9a61ad4b5992457169685c5c69e20889b5.diff
LOG: [libc++] Add the ability to run arbitrary programs using the DSL
This is useful for checking runtime properties of the target system.
This is a partial re-application of 3ea9450bda90. This part was tested
to work on a Windows host with a SSH executor.
Added:
Modified:
libcxx/test/libcxx/selftest/dsl/dsl.sh.py
libcxx/utils/libcxx/test/dsl.py
Removed:
################################################################################
diff --git a/libcxx/test/libcxx/selftest/dsl/dsl.sh.py b/libcxx/test/libcxx/selftest/dsl/dsl.sh.py
index b9437d6ca053..7205f35e7dc5 100644
--- a/libcxx/test/libcxx/selftest/dsl/dsl.sh.py
+++ b/libcxx/test/libcxx/selftest/dsl/dsl.sh.py
@@ -114,6 +114,56 @@ def test_link_error_fails(self):
int main(int, char**) { this_isnt_defined_anywhere(); }"""
self.assertFalse(dsl.sourceBuilds(self.config, source))
+class TestProgramOutput(SetupConfigs):
+ """
+ Tests for libcxx.test.dsl.programOutput
+ """
+ def test_valid_program_returns_output(self):
+ source = """
+ #include <cstdio>
+ int main(int, char**) { std::printf("FOOBAR"); }
+ """
+ self.assertEqual(dsl.programOutput(self.config, source), "FOOBAR")
+
+ def test_valid_program_returns_output_newline_handling(self):
+ source = """
+ #include <cstdio>
+ int main(int, char**) { std::printf("FOOBAR\\n"); }
+ """
+ self.assertEqual(dsl.programOutput(self.config, source), "FOOBAR\n")
+
+ def test_valid_program_returns_no_output(self):
+ source = """
+ int main(int, char**) { }
+ """
+ self.assertEqual(dsl.programOutput(self.config, source), "")
+
+ def test_invalid_program_returns_None_1(self):
+ # The program compiles, but exits with an error
+ source = """
+ int main(int, char**) { return 1; }
+ """
+ self.assertEqual(dsl.programOutput(self.config, source), None)
+
+ def test_invalid_program_returns_None_2(self):
+ # The program doesn't compile
+ source = """
+ int main(int, char**) { this doesnt compile }
+ """
+ self.assertEqual(dsl.programOutput(self.config, source), None)
+
+ def test_pass_arguments_to_program(self):
+ source = """
+ #include <cassert>
+ #include <string>
+ int main(int argc, char** argv) {
+ assert(argc == 3);
+ assert(argv[1] == std::string("first-argument"));
+ assert(argv[2] == std::string("second-argument"));
+ }
+ """
+ args = ["first-argument", "second-argument"]
+ self.assertEqual(dsl.programOutput(self.config, source, args=args), "")
class TestHasLocale(SetupConfigs):
"""
diff --git a/libcxx/utils/libcxx/test/dsl.py b/libcxx/utils/libcxx/test/dsl.py
index 3e2d0ed8ee33..475e19eae231 100644
--- a/libcxx/utils/libcxx/test/dsl.py
+++ b/libcxx/utils/libcxx/test/dsl.py
@@ -12,6 +12,7 @@
import os
import pipes
import platform
+import re
import tempfile
def _memoize(f):
@@ -75,6 +76,39 @@ def sourceBuilds(config, source):
_executeScriptInternal(test, ['rm %t.exe'])
return exitCode == 0
+def programOutput(config, program, args=[]):
+ """
+ Compiles a program for the test target, run it on the test target and return
+ the output.
+
+ If the program fails to compile or run, None is returned instead. Note that
+ execution of the program is done through the %{exec} substitution, which means
+ that the program may be run on a remote host depending on what %{exec} does.
+ """
+ with _makeConfigTest(config) as test:
+ with open(test.getSourcePath(), 'w') as source:
+ source.write(program)
+ try:
+ _, _, exitCode, _ = _executeScriptInternal(test, [
+ "mkdir -p %T",
+ "%{cxx} %s %{flags} %{compile_flags} %{link_flags} -o %t.exe",
+ ])
+ if exitCode != 0:
+ return None
+
+ out, err, exitCode, _ = _executeScriptInternal(test, [
+ "%{{exec}} %t.exe {}".format(' '.join(args))
+ ])
+ if exitCode != 0:
+ return None
+
+ actualOut = re.search("command output:\n(.+)\n$", out, flags=re.DOTALL)
+ actualOut = actualOut.group(1) if actualOut else ""
+ return actualOut
+
+ finally:
+ _executeScriptInternal(test, ['rm %t.exe'])
+
def hasCompileFlag(config, flag):
"""
Return whether the compiler in the configuration supports a given compiler flag.
@@ -96,22 +130,14 @@ def hasLocale(config, locale):
%{exec} -- this means that the command may be executed on a remote host
depending on the %{exec} substitution.
"""
- with _makeConfigTest(config) as test:
- with open(test.getSourcePath(), 'w') as source:
- source.write("""
- #include <locale.h>
- int main(int, char** argv) {
- if (::setlocale(LC_ALL, argv[1]) != NULL) return 0;
- else return 1;
- }
- """)
- out, err, exitCode, timeoutInfo = _executeScriptInternal(test, [
- "mkdir -p %T",
- "%{cxx} %s %{flags} %{compile_flags} %{link_flags} -o %t.exe",
- "%{{exec}} %t.exe {}".format(pipes.quote(locale)),
- ])
- _executeScriptInternal(test, ['rm %t.exe'])
- return exitCode == 0
+ program = """
+ #include <locale.h>
+ int main(int, char** argv) {
+ if (::setlocale(LC_ALL, argv[1]) != NULL) return 0;
+ else return 1;
+ }
+ """
+ return programOutput(config, program, args=[pipes.quote(locale)]) != None
def compilerMacros(config, flags=''):
"""
More information about the libcxx-commits
mailing list