mirror of
https://github.com/intel/llvm.git
synced 2026-01-24 17:01:00 +08:00
[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.
This commit is contained in:
@@ -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 <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):
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <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=''):
|
||||
"""
|
||||
|
||||
@@ -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 <cstdio>
|
||||
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
|
||||
}
|
||||
"""))
|
||||
]
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user