On Sat, Dec 5, 2020 at 2:18 AM Daniel Latypov dlatypov@google.com wrote:
On Thu, Dec 3, 2020 at 7:57 PM David Gow davidgow@google.com wrote:
On Fri, Dec 4, 2020 at 3:41 AM Daniel Latypov dlatypov@google.com wrote:
LinuxSourceTree will unceremoniously crash if the user doesn't call read_kunitconfig() first in a number of functions.
This patch seems to partly be reverting the changes here, right: https://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git/co... (That patch moved the reading of kunitconfig out of __init__)
Yes.
My overall concern is that, really, there are some operations that shouldn't need a kunitconfig (even if they do at the moment), so we'd ideally want at least some of the operations currently under LinuxSourceTree to be able to be run without first reading a kunitconfig. Most notably, it'd be nice if kunit.py exec (and hence LinuxSourceTree::run_kernel()) didn't need a kunitconfig, as the kernel ought to already be built at this point.
Now, this is all a little bit hypothetical, as we haven't bothered to make kunit.py exec work without a kunitconfig thus far, but I'm a touch hesitant to make it harder to bypass the kunitconfig reading anyway.
Fair point.
So one alternative to this to make type-checkers happy is to declare _config instead of sneakily setting it in some random later method. Then in all the places that rely on _config, we'd need to add in checks that it's in fact set to give a better error message (so it's clear to the user that it's an internal tool bug and has nothing to do with them).
This seems plausible, if a bit verbose.
The copy-paste of create+read_kunitconfig() is annoying, which is why I went with this.
Personally, the duplication of calls to {create,read}_kunitconfig() doesn't bother me, but I definitely can see the advantage of having the type system pick up when we've missed one.
How about __init__ takes an optional argument that can disable this parsing?
This would be okay: I'm starting to feel that really, the ultimate solution is either to split LinuxSourceTree up (and have separate things for configuring, building, and running the kernel), or to pass the kconfig stuff into just the functions that require it. But that is a much more serious refactor, which I haven't fully thought through, and I don't want to let the perfect be the enemy of the good here.
E.g.
def __init__(kconfig = None): if kconfig is not None: self._config = kconfig else: // create and read
What would the kconfig argument here be? Just an empty Kconfig()? I'm not a huge fan of passing a "None" kconfig object when we want to load a config, and a non-None one when we want an empty one: that seems confusingly backwards. Maybe it'd be possible to move the loading of the kunitconfig outside LinuxSourceTree, and pass that (or an empty one) as needed?
Or if we don't like the idea of requiring users who don't want a kconfig to pass in a dummy,
def __init__(load_kconfig=True): if not load_kconfig: self._config = None ...
I slightly prefer this, for the reasons above: True/False makes more sense than None/Kconfig().
Adn currently every place we create an instance, the caller also calls create_kunitconfig() and read_kunitconfig().
Move these instead into __init__() so they can't be forgotten and to reduce copy-paste.
This seems to now be missing the create_kunitconfig() stuff (see below).
Ah good catch. Completely unintentional. I'm sure I had the create_kunitconfig() stuff in __init__() at some point but must have inadvertently removed it somehow later on.
The https://github.com/google/pytype type-checker complained that _config wasn't initialized. With this, kunit_tool now type checks under both pytype and mypy.
Signed-off-by: Daniel Latypov dlatypov@google.com
Okay, so it looks like there are a few options with _kconfig: 1. Check for None everywhere (after explicitly setting it in the constructor). Pros: Nicer error messages, doesn't require other changes, Cons: verbose, still somewhat prone to error (could forget {create,read}_kunitconfig())
2. Pass a Kconfig object into the constructor. Pros: a kconfig must exist, so less error prone, Cons: if we allow passing None to load it, that's confusing.
3. Pass a bool into the constructor. Pros: similarly less error prone. Cons: True/False is not very descriptive.
4. Refactor and (e.g.) pass the kconfig only into functions which require it. Pros: removes a "false dependency" on a kconfig for things which don't need it. Cons: more work, more verbose.
Of these, I probably like them in this order 4, 2 (without None), 3, 2 (with None), 1. But, to be honest, I'd be happy enough with any of them.
So, if we can get a v2 that fixes the missing create_kunitconfig(), and does any of the above things, that sounds good to me.
Cheers, -- David