1from __future__ import absolute_import
2import os
3
4import lit.Test
5import lit.util
6
7class TestFormat(object):
8    pass
9
10###
11
12class FileBasedTest(TestFormat):
13    def getTestsInDirectory(self, testSuite, path_in_suite,
14                            litConfig, localConfig):
15        source_path = testSuite.getSourcePath(path_in_suite)
16        for filename in os.listdir(source_path):
17            # Ignore dot files and excluded tests.
18            if (filename.startswith('.') or
19                filename in localConfig.excludes):
20                continue
21
22            filepath = os.path.join(source_path, filename)
23            if not os.path.isdir(filepath):
24                base,ext = os.path.splitext(filename)
25                if ext in localConfig.suffixes:
26                    yield lit.Test.Test(testSuite, path_in_suite + (filename,),
27                                        localConfig)
28
29###
30
31import re
32import tempfile
33
34class OneCommandPerFileTest(TestFormat):
35    # FIXME: Refactor into generic test for running some command on a directory
36    # of inputs.
37
38    def __init__(self, command, dir, recursive=False,
39                 pattern=".*", useTempInput=False):
40        if isinstance(command, str):
41            self.command = [command]
42        else:
43            self.command = list(command)
44        if dir is not None:
45            dir = str(dir)
46        self.dir = dir
47        self.recursive = bool(recursive)
48        self.pattern = re.compile(pattern)
49        self.useTempInput = useTempInput
50
51    def getTestsInDirectory(self, testSuite, path_in_suite,
52                            litConfig, localConfig):
53        dir = self.dir
54        if dir is None:
55            dir = testSuite.getSourcePath(path_in_suite)
56
57        for dirname,subdirs,filenames in os.walk(dir):
58            if not self.recursive:
59                subdirs[:] = []
60
61            subdirs[:] = [d for d in subdirs
62                          if (d != '.svn' and
63                              d not in localConfig.excludes)]
64
65            for filename in filenames:
66                if (filename.startswith('.') or
67                    not self.pattern.match(filename) or
68                    filename in localConfig.excludes):
69                    continue
70
71                path = os.path.join(dirname,filename)
72                suffix = path[len(dir):]
73                if suffix.startswith(os.sep):
74                    suffix = suffix[1:]
75                test = lit.Test.Test(
76                    testSuite, path_in_suite + tuple(suffix.split(os.sep)),
77                    localConfig)
78                # FIXME: Hack?
79                test.source_path = path
80                yield test
81
82    def createTempInput(self, tmp, test):
83        raise NotImplementedError('This is an abstract method.')
84
85    def execute(self, test, litConfig):
86        if test.config.unsupported:
87            return (lit.Test.UNSUPPORTED, 'Test is unsupported')
88
89        cmd = list(self.command)
90
91        # If using temp input, create a temporary file and hand it to the
92        # subclass.
93        if self.useTempInput:
94            tmp = tempfile.NamedTemporaryFile(suffix='.cpp')
95            self.createTempInput(tmp, test)
96            tmp.flush()
97            cmd.append(tmp.name)
98        elif hasattr(test, 'source_path'):
99            cmd.append(test.source_path)
100        else:
101            cmd.append(test.getSourcePath())
102
103        out, err, exitCode = lit.util.executeCommand(cmd)
104
105        diags = out + err
106        if not exitCode and not diags.strip():
107            return lit.Test.PASS,''
108
109        # Try to include some useful information.
110        report = """Command: %s\n""" % ' '.join(["'%s'" % a
111                                                 for a in cmd])
112        if self.useTempInput:
113            report += """Temporary File: %s\n""" % tmp.name
114            report += "--\n%s--\n""" % open(tmp.name).read()
115        report += """Output:\n--\n%s--""" % diags
116
117        return lit.Test.FAIL, report
118
119
120###
121
122# Check exit code of a simple executable with no input
123class ExecutableTest(FileBasedTest):
124    def execute(self, test, litConfig):
125        if test.config.unsupported:
126            return lit.Test.UNSUPPORTED
127
128        out, err, exitCode = lit.util.executeCommand(test.getSourcePath())
129
130        if not exitCode:
131            return lit.Test.PASS, ''
132
133        return lit.Test.FAIL, out+err
134
135