From: Louis Dionne Date: Fri, 17 Apr 2020 20:00:58 +0000 (-0400) Subject: [libc++] Migrate Lit platform detection to the DSL X-Git-Tag: llvmorg-12-init~3244 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3ea9450bda902574426a847e290567ffaf6a6c40;p=platform%2Fupstream%2Fllvm.git [libc++] Migrate Lit platform detection to the DSL As an important fly-by fix, also make sure we set those features to their value on the target we run on, not on the host compiling the test suite. --- diff --git a/libcxx/test/libcxx/selftest/dsl/dsl.sh.py b/libcxx/test/libcxx/selftest/dsl/dsl.sh.py index 5a8ae88..b585241 100644 --- a/libcxx/test/libcxx/selftest/dsl/dsl.sh.py +++ b/libcxx/test/libcxx/selftest/dsl/dsl.sh.py @@ -114,6 +114,56 @@ class TestSourceBuilds(SetupConfigs): 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 + 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 + 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 + #include + 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/config.py b/libcxx/utils/libcxx/test/config.py index 44cb959..41c0b08 100644 --- a/libcxx/utils/libcxx/test/config.py +++ b/libcxx/utils/libcxx/test/config.py @@ -317,9 +317,6 @@ class Configuration(object): self.config.available_features.add('availability=%s' % name) self.config.available_features.add('availability=%s%s' % (name, version)) - # Insert the platform name and version into the available features. - self.target_info.add_platform_features(self.config.available_features) - # Simulator testing can take a really long time for some of these tests # so add a feature check so we can REQUIRES: long_tests in them self.long_tests = self.get_lit_bool('long_tests') @@ -333,7 +330,6 @@ class Configuration(object): self.config.available_features.add('long_tests') if self.target_info.is_windows(): - self.config.available_features.add('windows') if self.cxx_stdlib_under_test == 'libc++': # LIBCXX-WINDOWS-FIXME is the feature name used to XFAIL the # initial Windows failures until they can be properly diagnosed diff --git a/libcxx/utils/libcxx/test/dsl.py b/libcxx/utils/libcxx/test/dsl.py index bbed2bba..991e938 100644 --- a/libcxx/utils/libcxx/test/dsl.py +++ b/libcxx/utils/libcxx/test/dsl.py @@ -12,6 +12,7 @@ import lit.util 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 - 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 + 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=''): """ diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py index d00866d..ecce08d 100644 --- a/libcxx/utils/libcxx/test/features.py +++ b/libcxx/utils/libcxx/test/features.py @@ -7,6 +7,7 @@ #===----------------------------------------------------------------------===## from libcxx.test.dsl import * +import pipes import sys _isClang = lambda cfg: '__clang__' in compilerMacros(cfg) and '__apple_build_version__' not in compilerMacros(cfg) @@ -108,3 +109,24 @@ for locale, alts in locales.items(): Feature(name='locale.{}'.format(locale), when=lambda cfg: any(hasLocale(cfg, alt) for alt in alts)) ] + + +# Add a feature representing the platform name: darwin, linux, windows, etc... +features += [ + Feature(name=lambda cfg: programOutput(cfg, """ + #include + int main() { + #if defined(__APPLE__) + std::printf("darwin"); + #elif defined(_WIN32) + std::printf("windows"); + #elif defined(__NetBSD__) + std::printf("netbsd"); + #elif defined(__linux__) + std::printf("linux"); + #else + std::printf("unknown-platform"); + #endif + } + """)) +] diff --git a/libcxx/utils/libcxx/test/target_info.py b/libcxx/utils/libcxx/test/target_info.py index adc7048..a9abb43 100644 --- a/libcxx/utils/libcxx/test/target_info.py +++ b/libcxx/utils/libcxx/test/target_info.py @@ -21,23 +21,17 @@ class DefaultTargetInfo(object): self.full_config = full_config self.executor = None - def platform(self): - return sys.platform.lower().strip() - def is_windows(self): - return self.platform() == 'win32' + return sys.platform.lower().strip() == 'win32' def is_darwin(self): - return self.platform() == 'darwin' + return sys.platform.lower().strip() == 'darwin' def add_cxx_compile_flags(self, flags): pass def add_cxx_link_flags(self, flags): pass def allow_cxxabi_link(self): return True def use_lit_shell_default(self): return False - def add_platform_features(self, features): - features.add(self.platform()) - def add_path(self, dest_env, new_path): if not new_path: return @@ -143,44 +137,6 @@ class LinuxLocalTI(DefaultTargetInfo): def __init__(self, full_config): super(LinuxLocalTI, self).__init__(full_config) - def platform(self): - return 'linux' - - def _distribution(self): - try: - # linux_distribution is not available since Python 3.8 - # However, this function is only used to detect SLES 11, - # which is quite an old distribution that doesn't have - # Python 3.8. - return platform.linux_distribution() - except AttributeError: - return '', '', '' - - def platform_name(self): - name, _, _ = self._distribution() - # Some distros have spaces, e.g. 'SUSE Linux Enterprise Server' - # lit features can't have spaces - name = name.lower().strip().replace(' ', '-') - return name # Permitted to be None - - def platform_ver(self): - _, ver, _ = self._distribution() - ver = ver.lower().strip().replace(' ', '-') - return ver # Permitted to be None. - - def add_platform_features(self, features): - super(LinuxLocalTI, self).add_platform_features(features) - - # Some linux distributions have different locale data than others. - # Insert the distributions name and name-version into the available - # features to allow tests to XFAIL on them. - name = self.platform_name() - ver = self.platform_ver() - if name: - features.add(name) - if name and ver: - features.add('%s-%s' % (name, ver)) - def add_cxx_compile_flags(self, flags): flags += ['-D__STDC_FORMAT_MACROS', '-D__STDC_LIMIT_MACROS',