On Mon, Feb 18, 2019 at 2:56 PM Frank Rowand <frowand.list(a)gmail.com> wrote:
On 2/12/19 5:44 PM, Brendan Higgins wrote:
> On Wed, Nov 28, 2018 at 12:56 PM Rob Herring <robh(a)kernel.org> wrote:
>>
>> On Wed, Nov 28, 2018 at 1:38 PM Brendan Higgins
>> <brendanhiggins(a)google.com> wrote:
<snip>
>>> ---
>>> drivers/of/Kconfig | 1 +
>>> drivers/of/unittest.c | 1405 ++++++++++++++++++++++-------------------
>>> 2 files changed, 752 insertions(+), 654 deletions(-)
>>>
> <snip>
>>> diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
>>> index 41b49716ac75f..a5ef44730ffdb 100644
>>> --- a/drivers/of/unittest.c
>>> +++ b/drivers/of/unittest.c
<snip>
>>> +
>>> + KUNIT_EXPECT_EQ(test,
>>> + of_property_match_string(np,
>>> +
"phandle-list-names",
>>> + "first"),
>>> + 0);
>>> + KUNIT_EXPECT_EQ(test,
>>> + of_property_match_string(np,
>>> +
"phandle-list-names",
>>> + "second"),
>>> + 1);
>>
>> Fewer lines on these would be better even if we go over 80 chars.
Agreed. unittest.c already is a greater than 80 char file in general, and
is a file that benefits from that.
Noted.
> On the of_property_match_string(...), I have no opinion. I will do
> whatever you like best.
>
> Nevertheless, as far as the KUNIT_EXPECT_*(...), I do have an opinion: I am
> trying to establish a good, readable convention. Given an expect statement
> structured as
> ```
> KUNIT_EXPECT_*(
> test,
> expect_arg_0, ..., expect_arg_n,
> fmt_str, fmt_arg_0, ..., fmt_arg_n)
> ```
> where `test` is the `struct kunit` context argument, `expect_arg_{0, ..., n}`
> are the arguments the expectations is being made about (so in the above example,
> `of_property_match_string(...)` and `1`), and `fmt_*` is the optional format
> string that comes at the end of some expectations.
>
> The pattern I had been trying to promote is the following:
>
> 1) If everything fits on 1 line, do that.
> 2) If you must make a line split, prefer to keep `test` on its own line,
> `expect_arg_{0, ..., n}` should be kept together, if possible, and the format
> string should follow the conventions already most commonly used with format
> strings.
> 3) If you must split up `expect_arg_{0, ..., n}` each argument should get its
> own line and should not share a line with either `test` or any `fmt_*`.
>
> The reason I care about this so much is because expectations should be
> extremely easy to read; they are the most important part of a unit
> test because they tell you what the test is verifying. I am not
> married to the formatting I proposed above, but I want something that
> will be extremely easy to identify the arguments that the expectation
> is on. Maybe that means that I need to add some syntactic fluff to
> make it clearer, I don't know, but this is definitely something we
> need to get right, especially in the earliest examples.
I will probably raise the ire of the kernel formatting rule makers by offering
what I think is a _much_ more readable format __for this specific case__.
In other words for drivers/of/unittest.c.
If you can not make your mail window _very_ wide, or if this email has been
line wrapped, this example will not be clear.
Two possible formats:
### ----- version 1, as created by the patch series
static void of_unittest_property_string(struct kunit *test)
{
const char *strings[4];
struct device_node *np;
int rc;
np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np);
KUNIT_EXPECT_EQ(
test,
of_property_match_string(np, "phandle-list-names",
"first"),
0);
KUNIT_EXPECT_EQ(
test,
of_property_match_string(np, "phandle-list-names",
"second"),
1);
KUNIT_EXPECT_EQ(
test,
of_property_match_string(np, "phandle-list-names",
"third"),
2);
KUNIT_EXPECT_EQ_MSG(
test,
of_property_match_string(np, "phandle-list-names",
"fourth"),
-ENODATA,
"unmatched string");
KUNIT_EXPECT_EQ_MSG(
test,
of_property_match_string(np, "missing-property",
"blah"),
-EINVAL,
"missing property");
KUNIT_EXPECT_EQ_MSG(
test,
of_property_match_string(np, "empty-property",
"blah"),
-ENODATA,
"empty property");
KUNIT_EXPECT_EQ_MSG(
test,
of_property_match_string(np, "unterminated-string",
"blah"),
-EILSEQ,
"unterminated string");
/* of_property_count_strings() tests */
KUNIT_EXPECT_EQ(test,
of_property_count_strings(np, "string-property"), 1);
KUNIT_EXPECT_EQ(test,
of_property_count_strings(np, "phandle-list-names"),
3);
KUNIT_EXPECT_EQ_MSG(
test,
of_property_count_strings(np, "unterminated-string"), -EILSEQ,
"unterminated string");
KUNIT_EXPECT_EQ_MSG(
test,
of_property_count_strings(np, "unterminated-string-list"),
-EILSEQ,
"unterminated string array");
### ----- version 2, modified to use really long lines
static void of_unittest_property_string(struct kunit *test)
{
const char *strings[4];
struct device_node *np;
int rc;
np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np);
KUNIT_EXPECT_EQ( test, of_property_match_string(np,
"phandle-list-names", "first"), 0);
KUNIT_EXPECT_EQ( test, of_property_match_string(np,
"phandle-list-names", "second"), 1);
KUNIT_EXPECT_EQ( test, of_property_match_string(np,
"phandle-list-names", "third"), 2);
KUNIT_EXPECT_EQ_MSG(test, of_property_match_string(np,
"phandle-list-names", "fourth"), -ENODATA, "unmatched
string");
KUNIT_EXPECT_EQ_MSG(test, of_property_match_string(np,
"missing-property", "blah"), -EINVAL, "missing
property");
KUNIT_EXPECT_EQ_MSG(test, of_property_match_string(np,
"empty-property", "blah"), -ENODATA, "empty
property");
KUNIT_EXPECT_EQ_MSG(test, of_property_match_string(np,
"unterminated-string", "blah"), -EILSEQ, "unterminated
string");
/* of_property_count_strings() tests */
KUNIT_EXPECT_EQ( test, of_property_count_strings(np,
"string-property"), 1);
KUNIT_EXPECT_EQ( test, of_property_count_strings(np,
"phandle-list-names"), 3);
KUNIT_EXPECT_EQ_MSG(test, of_property_count_strings(np,
"unterminated-string"), -EILSEQ, "unterminated string");
KUNIT_EXPECT_EQ_MSG(test, of_property_count_strings(np,
"unterminated-string-list"), -EILSEQ, "unterminated string
array");
------------------------
-------------------------------------------------------------
--------------------------------------
^ ^
^
| |
|
| |
|
mostly boilerplate what is being tested
expected result, error message
(can vary in relop
and _MSG or not)
In my opinion, the second version is much more readable. It is easy to see the
differences in the boilerplate. It is easy to see what is being tested, and how
the arguments of the tested function vary for each test. It is easy to see the
expected result and error message. The entire block fits into a single short
window (though much wider).
I have no opinion on the over 80 char thing, so as long as everyone
else is okay with it, I have no complaints.
Cheers