summaryrefslogtreecommitdiff
path: root/testsuite
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite')
-rw-r--r--testsuite/config/ghc27
-rw-r--r--testsuite/driver/runtests.py16
-rw-r--r--testsuite/driver/testlib.py6
-rw-r--r--testsuite/mk/ghc-config.hs5
-rw-r--r--testsuite/mk/test.mk8
-rw-r--r--testsuite/tests/linters/Makefile4
-rw-r--r--testsuite/tests/linters/all.T1
-rwxr-xr-xtestsuite/tests/linters/checkUniques/check-uniques.py49
8 files changed, 85 insertions, 31 deletions
diff --git a/testsuite/config/ghc b/testsuite/config/ghc
index aed4c22fb0..1a73e3a547 100644
--- a/testsuite/config/ghc
+++ b/testsuite/config/ghc
@@ -183,18 +183,6 @@ llvm_ways = [x[0] for x in config.way_flags.items()
def get_compiler_info():
- s = getStdout([config.compiler, '--info'])
- s = re.sub('[\r\n]', '', s)
- compilerInfoDict = dict(eval(s))
- s = getStdout([config.compiler, '+RTS', '--info'])
- s = re.sub('[\r\n]', '', s)
- rtsInfoDict = dict(eval(s))
-
- config.have_ncg = compilerInfoDict.get("Have native code generator", "NO") == "YES"
-
- # Detect whether an LLVM toolhain is available
- llc_path = compilerInfoDict.get("LLVM llc command")
- config.have_llvm = shutil.which(llc_path) is not None
if config.unregisterised:
print("Unregisterised build; skipping LLVM ways...")
elif config.have_llvm:
@@ -212,25 +200,14 @@ def get_compiler_info():
# backend by default.
config.ghc_built_by_llvm = not config.have_ncg and not config.unregisterised
- config.have_RTS_linker = compilerInfoDict.get("target has RTS linker", "NO") == "YES"
# external interpreter needs RTS linker support
# If the field is not present (GHC 8.0 and earlier), assume we don't
# have -fexternal-interpreter (though GHC 8.0 actually does)
# so we can still run most tests.
- config.have_ext_interp = compilerInfoDict.get("target has RTS linker", "NO") == "YES"
+ config.have_ext_interp = config.have_RTS_linker
# See Note [Replacing backward slashes in config.libdir].
- config.libdir = compilerInfoDict['LibDir'].replace('\\', '/')
-
- if re.match(".*_p(_.*|$)", rtsInfoDict["RTS way"]):
- config.compiler_profiled = True
- else:
- config.compiler_profiled = False
-
- try:
- config.package_conf_cache_file = compilerInfoDict["Global Package DB"] + '/package.cache'
- except:
- config.package_conf_cache_file = ''
+ config.libdir = config.libdir.replace('\\', '/')
# See Note [WayFlags]
if config.ghc_dynamic:
diff --git a/testsuite/driver/runtests.py b/testsuite/driver/runtests.py
index 6858715c7a..d2e25eaa19 100644
--- a/testsuite/driver/runtests.py
+++ b/testsuite/driver/runtests.py
@@ -275,12 +275,18 @@ def format_path(path):
# On Windows we need to set $PATH to include the paths to all the DLLs
# in order for the dynamic library tests to work.
if windows:
- pkginfo = getStdout([config.ghc_pkg, 'dump'])
+ try:
+ pkginfo = getStdout([config.ghc_pkg, 'dump'])
+ except FileNotFoundError as err:
+ # This can happen when we are only running tests which don't depend on ghc (ie linters)
+ # In that case we probably haven't built ghc-pkg yet so this query will fail.
+ print (err)
+ print ("Failed to call ghc-pkg for windows path modification... some tests might fail")
+ pkginfo = ""
topdir = config.libdir
- if windows:
- mingw = os.path.abspath(os.path.join(topdir, '../mingw/bin'))
- mingw = format_path(mingw)
- ghc_env['PATH'] = os.pathsep.join([ghc_env.get("PATH", ""), mingw])
+ mingw = os.path.abspath(os.path.join(topdir, '../mingw/bin'))
+ mingw = format_path(mingw)
+ ghc_env['PATH'] = os.pathsep.join([ghc_env.get("PATH", ""), mingw])
for line in pkginfo.split('\n'):
if line.startswith('library-dirs:'):
path = line.rstrip()
diff --git a/testsuite/driver/testlib.py b/testsuite/driver/testlib.py
index 423cd99313..74ba9909f1 100644
--- a/testsuite/driver/testlib.py
+++ b/testsuite/driver/testlib.py
@@ -125,6 +125,12 @@ def setTestOpts( f ):
# type TestOpt = (name :: String, opts :: Object) -> IO ()
def normal( name, opts ):
+ opts.hadrian_deps.update(["test:ghc"])
+ return;
+
+# A test with no hadrian built dependencies, including the test compiler
+# This is used for linters.
+def no_deps( name, opts):
return;
def skip( name, opts ):
diff --git a/testsuite/mk/ghc-config.hs b/testsuite/mk/ghc-config.hs
index e4631f13ff..a22d9b46d1 100644
--- a/testsuite/mk/ghc-config.hs
+++ b/testsuite/mk/ghc-config.hs
@@ -20,12 +20,15 @@ main = do
getGhcFieldOrFail fields "GhcDebugged" "Debug on"
getGhcFieldOrFail fields "GhcWithNativeCodeGen" "Have native code generator"
getGhcFieldOrFail fields "GhcWithInterpreter" "Have interpreter"
+ getGhcFieldOrFail fields "GhcWithRtsLinker" "target has RTS linker"
getGhcFieldOrFail fields "GhcUnregisterised" "Unregisterised"
getGhcFieldOrFail fields "GhcWithSMP" "Support SMP"
getGhcFieldOrFail fields "GhcRTSWays" "RTS ways"
- getGhcFieldOrFail fields "GhcLeadingUnderscore" "Leading underscore"
+ getGhcFieldOrFail fields "GhcLibdir" "LibDir"
+ getGhcFieldOrFail fields "GhcGlobalPackageDb" "Global Package DB"
getGhcFieldOrDefault fields "GhcDynamic" "GHC Dynamic" "NO"
getGhcFieldOrDefault fields "GhcProfiled" "GHC Profiled" "NO"
+ getGhcFieldOrDefault fields "LeadingUnderscore" "Leading underscore" "NO"
getGhcFieldProgWithDefault fields "AR" "ar command" "ar"
getGhcFieldProgWithDefault fields "CLANG" "LLVM clang command" "clang"
getGhcFieldProgWithDefault fields "LLC" "LLVM llc command" "llc"
diff --git a/testsuite/mk/test.mk b/testsuite/mk/test.mk
index e01a76eb29..56c720f0fd 100644
--- a/testsuite/mk/test.mk
+++ b/testsuite/mk/test.mk
@@ -189,6 +189,14 @@ else
RUNTEST_OPTS += -e ghc_with_smp=False
endif
+ifeq "$(GhcWithRtsLinker)" "YES"
+RUNTEST_OPTS += -e config.have_RTS_linker=True
+else
+RUNTEST_OPTS += -e config.have_RTS_linker=False
+endif
+
+RUNTEST_OPTS += -e config.libdir="\"$(GhcLibdir)\""
+
ifeq "$(WINDOWS)" "YES"
RUNTEST_OPTS += -e windows=True
else
diff --git a/testsuite/tests/linters/Makefile b/testsuite/tests/linters/Makefile
new file mode 100644
index 0000000000..aeaef050e1
--- /dev/null
+++ b/testsuite/tests/linters/Makefile
@@ -0,0 +1,4 @@
+TOP=../..
+
+uniques:
+ python3 checkUniques/check-uniques.py $(TOP)/..
diff --git a/testsuite/tests/linters/all.T b/testsuite/tests/linters/all.T
new file mode 100644
index 0000000000..b4cc4bb8b3
--- /dev/null
+++ b/testsuite/tests/linters/all.T
@@ -0,0 +1 @@
+test('uniques', [no_deps, extra_files(["checkUniques"])], makefile_test, ['uniques'])
diff --git a/testsuite/tests/linters/checkUniques/check-uniques.py b/testsuite/tests/linters/checkUniques/check-uniques.py
new file mode 100755
index 0000000000..dd5891b0d8
--- /dev/null
+++ b/testsuite/tests/linters/checkUniques/check-uniques.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+
+import os.path
+import sys
+import re
+import glob
+import io
+from collections import defaultdict
+
+# keyed on unique type, values are lists of (unique, name) pairs
+def find_uniques(source_files):
+ uniques = defaultdict(lambda: defaultdict(lambda: set()))
+ unique_re = re.compile(r"([\w\d]+)\s*=\s*mk([\w\d']+)Unique\s+(\d+)")
+ for f in source_files:
+ ms = unique_re.findall(io.open(f, encoding='utf8').read())
+ for name, _type, n in ms:
+ uniques[_type][int(n)].add(name)
+
+ return uniques
+
+def print_all(uniques):
+ for _type, uniqs in uniques.items():
+ print('{_type} uniques'.format(**locals()))
+ for n,names in uniqs.items():
+ all_names = ', '.join(names)
+ print(' {n} = {all_names}'.format(**locals()))
+
+def find_conflicts(uniques):
+ return [ (uniqueType, number, names)
+ for uniqueType, uniqs in uniques.items()
+ for number, names in uniqs.items()
+ if len(names) > 1
+ ]
+
+top_dir = sys.argv[1]
+uniques = find_uniques(glob.glob(os.path.join(top_dir, 'compiler', 'GHC', '**', '*.hs'), recursive=True))
+#print_all(uniques)
+conflicts = find_conflicts(uniques)
+if len(uniques) < 5:
+ print("Error: check-uniques: run from wrong directory?")
+ sys.exit(1)
+
+if len(conflicts) > 0:
+ print("Error: check-uniques: Found Unique conflict")
+ print()
+ for (ty, n, names) in conflicts:
+ print(' %s unique %d conflict: %s' % (ty, n, ', '.join(names)))
+ print()
+ sys.exit(1)