Skip to content

Commit 17b42ff

Browse files
Add 3c-regtest.py and migrate one example test to use it.
Comment about #_MARKER_# added.
1 parent 9a8a7b2 commit 17b42ff

File tree

2 files changed

+112
-6
lines changed

2 files changed

+112
-6
lines changed

clang/test/3C/3c-regtest.py

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#!/usr/bin/env python
2+
#
3+
# Usage: 3c-regtest -t TMPNAME [options...] SRC_FILE
4+
#
5+
# TMPNAME corresponds to %t and SRC_FILE corresponds to %s. Both are required.
6+
#
7+
# --subst can be used for things such as %clang, for example (assuming single
8+
# --quotes are removed by the shell):
9+
#
10+
# --subst %clang 'clang -some-flag'
11+
#
12+
# (Note: A literal % has to be represented as %% in a RUN line. If we instead
13+
# established the convention of automatically prepending the % here, then the
14+
# RUN line would trip the "Do not use 'clang' in tests, use '%clang'." error.)
15+
#
16+
# Example RUN line:
17+
#
18+
# // RUN: %S/3c-regtest.py -t %t --subst %%clang '%clang' %s
19+
#
20+
# Soon, we'll add options for different kinds of 3C regression tests.
21+
22+
# TODO: Add Windows compatibility code once we have an easy way to test on Windows.
23+
24+
import sys
25+
import os
26+
import platform
27+
import argparse
28+
29+
sys.path.insert(0, os.path.dirname(__file__) + '/../../../llvm/utils/lit')
30+
import lit.TestRunner
31+
32+
print "NOTICE: cwd is %s" % os.getcwd()
33+
34+
def die(msg):
35+
sys.stderr.write('Error: %s\n' % msg)
36+
sys.exit(1)
37+
38+
parser = argparse.ArgumentParser(description='Run a 3C regression test.')
39+
# TODO: Add help
40+
parser.add_argument('test_file')
41+
parser.add_argument('-t', required=True)
42+
parser.add_argument('--subst', action='append', nargs=2, default=[])
43+
args = parser.parse_args()
44+
45+
test_dir = os.path.dirname(args.test_file)
46+
if test_dir == '':
47+
test_dir = '.'
48+
49+
tmpName = args.t
50+
tmpNameSuffix = '.tmp'
51+
if tmpName.endswith(tmpNameSuffix):
52+
tmpBase = tmpName[:-len(tmpNameSuffix)]
53+
else:
54+
die('-t argument %s does not end with %s' % (tmpName, tmpNameSuffix))
55+
56+
substitutions = [
57+
# #_MARKER_# is a hack copied from getDefaultSubstitutions in
58+
# llvm/utils/lit/lit/TestRunner.py. To explain it a bit more fully:
59+
# applySubstitutions processes each before/after pair in turn and replaces
60+
# all occurrences. So if we simply put ('%%', '%') as either the first or
61+
# last pair, there is a risk of a % being interpreted as part of a %s, etc.
62+
# Instead, we temporarily replace %% with a string that doesn't contain %
63+
# and that we assume doesn't occur elsewhere in the commands. The "proper"
64+
# way to implement this kind of substitution processing is to make one pass
65+
# over the input from left to right, replacing codes as they are found, but
66+
# apparently that wasn't worth the extra code in `lit`.
67+
('%%', '#_MARKER_#'),
68+
('%s', args.test_file),
69+
('%S', test_dir),
70+
('%t', tmpName),
71+
]
72+
substitutions.extend(args.subst)
73+
substitutions.append(('#_MARKER_#', '%'))
74+
75+
# Starting with processor.py because it's always the same.
76+
commands = [
77+
# FIXME: 'foo.c' + 'hecked.c' is a terrible hack; find the right way to do this.
78+
'3c -alltypes -addcr %s -- | FileCheck -match-full-lines -check-prefixes="CHECK_ALL","CHECK" %s',
79+
'3c -addcr %s -- | FileCheck -match-full-lines -check-prefixes="CHECK_NOALL","CHECK" %s',
80+
'3c -addcr %s -- | %clang -c -fcheckedc-extension -x c -o /dev/null -',
81+
'3c -output-postfix=checked -alltypes %s',
82+
'3c -alltypes %shecked.c -- | count 0',
83+
'rm %shecked.c',
84+
]
85+
commands = lit.TestRunner.applySubstitutions(commands, substitutions)
86+
87+
class FakeTestConfig:
88+
def __init__(self):
89+
self.pipefail = True # Is this always OK?
90+
self.environment = dict(os.environ)
91+
92+
class FakeTest:
93+
def __init__(self):
94+
self.config = FakeTestConfig()
95+
96+
class FakeLitConfig:
97+
def __init__(self):
98+
self.isWindows = platform.system() == 'windows'
99+
# Let the calling `lit` handle any timeout.
100+
self.maxIndividualTestTime = 0
101+
102+
res = lit.TestRunner.executeScriptInternal(
103+
FakeTest(), FakeLitConfig(), tmpBase, commands, os.getcwd())
104+
if isinstance(res, lit.Test.Result):
105+
die('Error: executeScriptInternal returned unexpected Result(%s, %r)' %
106+
(res.code.name, res.output))
107+
108+
out, err, exitCode, timeoutInfo = res
109+
sys.stdout.write(out)
110+
sys.stderr.write(err)
111+
sys.exit(exitCode)

clang/test/3C/b9_allsafestructp.c

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
// RUN: 3c -alltypes -addcr %s -- | FileCheck -match-full-lines -check-prefixes="CHECK_ALL","CHECK" %s
2-
// RUN: 3c -addcr %s -- | FileCheck -match-full-lines -check-prefixes="CHECK_NOALL","CHECK" %s
3-
// RUN: 3c -addcr %s -- | %clang -c -fcheckedc-extension -x c -o /dev/null -
4-
// RUN: 3c -output-postfix=checked -alltypes %s
5-
// RUN: 3c -alltypes %S/b9_allsafestructp.checked.c -- | count 0
6-
// RUN: rm %S/b9_allsafestructp.checked.c
1+
// RUN: %S/3c-regtest.py -t %t --subst %%clang '%clang' %s
72
#include <stddef.h>
83
#include <stddef.h>
94
extern _Itype_for_any(T) void *calloc(size_t nmemb, size_t size) : itype(_Array_ptr<T>) byte_count(nmemb * size);

0 commit comments

Comments
 (0)