[PATCH] [LIT] Add SuffixDispatchTest for use in libc++ and libc++abi tests.
Dan Albert
danalbert at google.com
Thu Nov 13 11:13:37 PST 2014
================
Comment at: utils/lit/lit/formats/suffixdispatchtest.py:22
@@ +21,3 @@
+
+ def add_suffix_test(self, suffix, test_runner):
+ self.suffix_tests += [tuple((suffix, test_runner))]
----------------
EricWF wrote:
> danalbert wrote:
> > Is there ever a case where these aren't known at initialization time of the object? I'd vote for just removing these two methods (especially delete).
> Perhaps. I need to look into this more but the use case I envisioned was that sub directories may want to add/remove test suffixes.
Hmm. I'm guessing YAGNI. Even if some subdirectory has different needs (sounds unlikely), they can just add it at the top level.
================
Comment at: utils/lit/lit/formats/suffixdispatchtest.py:106
@@ +105,3 @@
+ test_runner = None
+ for suffix_test in self.suffix_tests:
+ if name.endswith(suffix_test[0]):
----------------
EricWF wrote:
> danalbert wrote:
> > EricWF wrote:
> > > jroelofs wrote:
> > > > I think you can do this in python....
> > > >
> > > > for (suffix, test) in self.suffix_tests:
> > > > if name.endswith(suffix):
> > > > test_runner = test
> > > > break
> > > Cool! That's so much cleaner. Thanks.
> > You wanted a dict.
> >
> > test_runners = {
> > ".pass": PassRunner(),
> > ".fail": FailRunner()
> > }
> >
> > This block would become `test_runner = test_runners[suffix]`.
> I disagree. The problem is that I don't know how to split the filename into name + suffix. For example a `test.fail.cpp`. How do you know where to split the test name?
What's wrong with `testname.split('.')[-2]`?
================
Comment at: utils/lit/lit/formats/suffixdispatchtest.py:159
@@ +158,3 @@
+ cmd.append(exec_path)
+ if lit_config.useValgrind:
+ cmd = lit_config.valgrindArgs + cmd
----------------
EricWF wrote:
> danalbert wrote:
> > This looks like an implementation detail that leaked (though I appreciate the irony).
> >
> > I'd like to see if we can factor this out some how... but I'm not coming up with anything right now.
> I'm more alright having this here as opposed to in libc++ and libc++abi's lit.cfg. The valgrind stuff is all defined by lit (and is not local to libc++).
Ah, didn't realize it was a common LIT thing. Works for me.
================
Comment at: utils/lit/lit/util.py:149
@@ +148,3 @@
+
+def _to_string(str_bytes):
+ if isinstance(str_bytes, str):
----------------
EricWF wrote:
> danalbert wrote:
> > jroelofs wrote:
> > > Some comments on these two functions would be nice here to explain the "why" behind them. At the moment I don't understand why these are needed.
> > Yeah, I find it really difficult to believe that a python library needs its own `to_string`.
> Not sure. These already existed in the utility library. I'm just trying not to break them :S. I'll inquire as to why they are needed.
Well, looking at it, it's for handling transformation of a unicode byte-string into a text string... but what I don't understand is why we'd ever have to deal with that input...
================
Comment at: utils/lit/lit/util.py:189
@@ -165,1 +188,3 @@
+
+def executeCommandPTY(command, cwd=None, env=None):
try:
----------------
EricWF wrote:
> danalbert wrote:
> > Why do we need this? What's wrong with `subprocess.Popen(..., stdout=subprocess.PIPE, stderr=subprocess.PIPE)`?
> Color output! By tricking the sub process into thinking it's running in a TTY it will produce color output. I HATE that we currently lose clang pretty formatting when it gets passed through LIT.
Oh, yeah, that's rather nice. The implementation is rather disgusting though :) (I blame `subprocess.Popen`, not you).
What's wrong with `-fcolorize=always`?
If `-fcolorize=always` won't work, I think it would be better to make a `PtyPipe` class and pass that to executeCommand (with the default arugments being `subprocess.PIPE`).
================
Comment at: utils/lit/lit/util.py:206
@@ +205,3 @@
+ while True:
+ exitCode = p.poll()
+ if exitCode is not None:
----------------
EricWF wrote:
> danalbert wrote:
> > `exit_code`
> exitCode is the current naming in the rest of this file.
`out_pty` and `err_pty` are the other style though. Let's be consistent throughout the file, whatever that may be.
================
Comment at: utils/lit/lit/util.py:276
@@ +275,3 @@
+
+class Compiler(object):
+ def __init__(self, path, compile_flags=[], link_flags=[]):
----------------
EricWF wrote:
> danalbert wrote:
> > `lit.util` doesn't seem like the right place for this (but I haven't had a look around to know what the right place would be).
> Your probably right but IDK where to put it either. It's a surprising useful abstraction.
We can keep it here for now if no one has a better home for it,
================
Comment at: utils/lit/lit/util.py:279
@@ +278,3 @@
+ self.path = str(path)
+ self.compile_flags = list(compile_flags)
+ self.link_flags = list(link_flags)
----------------
EricWF wrote:
> danalbert wrote:
> > The copy probably isn't necessary.
> I disagree. I already have a use-case for it in the patch that makes libc++ use this.
>
> ```
> compile_flags = [...]
> cxx = Compiler(compile_flags)
> compile_flags.extend(sanitizer_args)
> sanitized_cxx = Compiler(compile_flags)
> ```
This might be the functional programmer in me showing, but I would write that as
compile_flags = [...]
cxx = Compiler(compile_flags)
sanitized_cxx = Compiler(compile_flags + sanitizer_args)
================
Comment at: utils/lit/lit/util.py:282
@@ +281,3 @@
+
+ def clone(self):
+ return Compiler(self.path, self.compile_flags, self.link_flags)
----------------
EricWF wrote:
> danalbert wrote:
> > Isn't this implicit?
> Don't think so. Python has shallow copy semantics on classes right?
I suppose this depends on the resolution of the comments on 279. I think a shallow copy should be sufficient.
================
Comment at: utils/lit/lit/util.py:285
@@ +284,3 @@
+
+ def compileCmd(self, compile_flags=[]):
+ return [self.path, '-c'] + self.compile_flags + compile_flags
----------------
EricWF wrote:
> danalbert wrote:
> > For the way this is used, I think `def compilerCmd(self, in, out)` would make more sense.
> >
> > Same goes for the rest of these.
> I still want to provide extra compile and link flags. meaning that the interface would look like:
> ```
> def compileCmd(self, in, out=None, compile_flags=[])
> ```
> Now you have to name the extra flags if you want to pass them. Instead I really thinks it's cleaner to let the user just pass arbitrary flags.
> If you feel strongly I'll make the change, but I had originally implemented it as you suggested and I really didn't like it.
The above interface looks right to me.
Keep in mind that hard coding the `-o` at the call site means that we'll have implementation details of the compiler leaking out of the abstraction and each call site will be
if compiler_under_test_is_msvc:
compiler.compileCmd(whatever_msvc_needs)
else:
compiler.compileCmd(['-o', out_file, in_file])
The `Compiler` should be an abstraction. How the compiler (the actual compiler, not `Compiler`) works should be irrelevant from the outside.
http://reviews.llvm.org/D6206
More information about the llvm-commits
mailing list